内部模板类型std :: vector <std :: vector <T >>的功能模板重载或特化

时间:2019-12-24 06:35:38

标签: c++ templates overloading stdvector template-specialization

如何为内部模板类型std::vector<std::vector<T>>实现模板重载功能。

我有一个程序,其中包含重载模板和具有映射,对和向量的复杂数据结构。

#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
} 

总是为矢量调用2,但是对于std::vectors<std::vector<T>>,我需要#5进行调用,并且我也收到编译错误w.r.t ::在std :: enable_if中使用的:: type。 请让我知道该程序有什么问题以及如何使其起作用。 也可以解释一下#6和#7代表w.r.t模板参数包是什么,它是如何工作的。

谢谢。

1 个答案:

答案 0 :(得分:3)

我看到为std::vector<std::vector<T>>编写f()专业化知识的最简单方法是

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

通过这种方式,您可以使模板f()的功能比#2更专业。

如果您想将SFINAE与is_specialization一起使用,在我看来,正确的方法是以下

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;
 }

不幸的是,此版本专用于版本#2,因此,当您使用f()调用std::vector<std::vector<T>>时,会产生歧义,从而导致编译错误。

要解决此问题,您还必须禁用#2版本

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;
 }

在原始版本中,您使用typename T::type ...,但是如果T不是定义了type的类,则会出现错误。

更多:您返回两种类型

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

以这种方式使用SFINAE,返回的类型必须由std::enable_if

表示