Function Template Overloading or Specialization for inner template type std::vector<std::vector<T>>

纵然是瞬间 提交于 2020-01-14 14:01:29

问题


How to achieve function Template Overloading for inner template type std::vector<std::vector<T>>.

I have a program of overloaded templates and a complex data structure having maps, pairs and vectors.

#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <typeinfo>

template<typename Test, template<typename...> class Ref> //#6
struct is_specialization : std::false_type {};

template<template<typename...> class Ref, typename... Args> //#7
struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
template <typename T>
bool f(T& x) // #1
{
    std::cout << "body of f\n";
    return f(x);
}

template <typename T>
bool f(std::vector<T>& v) // #2
{
    std::cout << "body of f for vectors\n";
    return true;
}
template<typename T>
typename std::enable_if<is_specialization<typename T::value, std::vector>::value, T>::type
    bool f(std::vector<T>& v) // #5
    {
        std::cout << "body of f for vectors<vectors>\n";
        return true;
    }

template <typename Key, typename Value>
bool f(const std::pair<Key,Value>& v) // #3
{
    std::cout << "body of f for pairs\n";
    for(auto& e: v) {
      f(e.first);
    }
    for(auto& e: v) {
      f(e.second);
    }
    return true;
}

template <typename Key, typename Value>
bool f(std::map<Key,Value>& v) // #4
{
    std::cout << "body of f for maps\n";
    for(auto& e: v) {
      f(e.first);  // expecting this call goes to #3
    }
    for(auto& e: v) {
      f(e.second);
    }
    return true;
}

int main() {
  std::vector<int> v{1,2};
  std::map<std::pair<int,int>,std::vector<std::vector<int>>> m_map = {
                                            {{10,20}, {{5,6},{5,6,7}}},
                                            {{11,22}, {{7,8},{7,8,9}}}
                                        };
    f(m_map); // this call goes to #4
} 

Always for vectors #2 is getting called, but for std::vectors<std::vector<T>> I need #5 to get called and also I am getting compilation error w.r.t ::type used in std::enable_if. Please let me know what is wrong in this program and how to make it work. Also Can some one explain what does #6 and #7 signify w.r.t template parameter pack, how does it work.

Thanks.


回答1:


The simplest way I see to write a std::vector<std::vector<T>> specialization for f() is the following

template<typename T>
bool f (std::vector<std::vector<T>>& v) // #5
 {
   std::cout << "body of f for vectors<vectors>\n";
   return true;
 }

This way you have overloaded template f() function that is more specialized than #2.

If you want to use SFINAE with your is_specialization, seems to me that the right way is the following

template <typename T>
typename std::enable_if<is_specialization<T, std::vector>::value, bool>::type
f (std::vector<T> & v) // #5
 {
   std::cout << "body of f for vectors<vectors>\n";
   return true;
 }

Unfortunately this version is specialized as version #2, so when you call f() with a std::vector<std::vector<T>>, you get an ambiguity so a compilation error.

To solve this problem you have also to disable the #2 version

template <typename T>
typename std::enable_if<! is_specialization<T, std::vector>::value, bool>::type
f (std::vector<T> & v) // #2
 {
   std::cout << "body of f for vectors\n";
   return true;
 }

In your original version... you use typename T::type... but this gives an error when T isn't a class with a type defined.

More: you return two types

template<typename T>
typename std::enable_if<is_specialization<typename T::value,
                        std::vector>::value, T>::type // <<--- type 1: T
    bool f(std::vector<T>& v) // #5
//  ^^^^  type2: bool

Using SFINAE this way, the returned type has to be expressed by std::enable_if



来源:https://stackoverflow.com/questions/59464774/function-template-overloading-or-specialization-for-inner-template-type-stdvec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!