如何为矢量和列表类型进行模板函数专业化

时间:2018-01-20 18:57:26

标签: c++

我尝试实现模板功能专业化。你可以在this小提琴中运行我的小代码。你也可以在下面看到它

#include <iostream>
#include <vector>
#include <list>


template <typename T>
struct is_vector {
    static const bool value = false;
};

template <typename T>
struct is_vector<std::vector<T>> {
    static const bool value = true;
    using type = std::vector<T>;
};

template <typename T>
struct is_list {
    static const bool value = false;
};

template <typename T>
struct is_list<std::list<T>> {
    static const bool value = true;
    using type = std::list<T>;
};


template<typename T, class = typename std::enable_if<is_list<T>::value>::type>
void foo(T t) {
    std::cout << "is list" << std::endl;
}

/*
template<typename T, class = typename std::enable_if<is_vector<T>::value>::type>
void foo(T t) {
    std::cout << "is vector" << std::endl;
}
*/
//The above code will cause an error, if we uncomment it

int main()
{

    foo(std::list<int>{});    

    return 0;
}

在这段代码中,我有几行注释:

template<typename T, class = typename std::enable_if<is_vector<T>::value>::type>
void foo(T t) {
    std::cout << "is vector" << std::endl;
}

如果我取消注释,我会得到&#34; redtifinition&#34;错误。我不确定如何解决它。

3 个答案:

答案 0 :(得分:3)

  

如果我取消注释,我会收到“redifinition”错误。我不确定如何解决它。

原因很简单:模板类型参数的默认值不是函数签名的一部分。这意味着您有两次定义相同的模板。

您可以将 SFINAE 部分移入函数返回类型,如其他答案所示,或将代码更改为:

template<typename T, std::enable_if_t<is_list<T>::value, int> = 0>
void foo(T t) {
    std::cout << "is list" << std::endl;
}

template<typename T, std::enable_if_t<is_vector<T>::value, int> = 1>
void foo(T t) {
    std::cout << "is vector" << std::endl;
}

答案 1 :(得分:1)

不确定这是否是您所追求的,但您可以检查列表或向量是否匹配类型:

template<typename T, class = typename std::enable_if<is_list<T>::value || is_vector<T>::value>::type>
void foo(T t) {
    std::cout << "is list" << std::endl;
}

更新了小提琴:https://godbolt.org/g/oD3o9q

更新(对于C ++ 14):

template<typename T, class = std::enable_if_t<is_list<T>::value || is_vector<T>::value>>
void foo(T t) {
    std::cout << "is list" << std::endl;
}

答案 2 :(得分:1)

你可以这样做。

template<typename T>
typename std::enable_if<is_list<T>::value>::type foo(T t) {
    std::cout << "is list" << std::endl;
}


template<typename T>
typename std::enable_if<is_vector<T>::value>::type foo(T t) {
    std::cout << "is vector" << std::endl;
}