#include <vector>
#include <list>
#include <iostream>
template
<
typename T,
template<typename, typename = std::allocator<T>> class C,
typename = std::enable_if_t
<
std::is_same<std::vector<T>, C<T>>::value
>
>
void f(const C<T>& coll)
{
std::cout << "vector" << std::endl;
}
template
<
typename T,
template<typename, typename = std::allocator<T>> class C,
typename = std::enable_if_t
<
std::is_same<std::list<T>, C<T>>::value
>
>
void f(const C<T>& coll)
{
std::cout << "list" << std::endl;
}
int main()
{
std::vector<int> c1{ 1, 2, 3 };
std::list<int> c2{ 1, 2, 3 };
f(c1);
f(c2);
}
Clang 3.8抱怨:
错误:模板参数重新定义默认参数:typename = std :: enable_if_t
代码中有什么问题?
答案 0 :(得分:2)
默认模板参数不参与功能匹配 从编译器的角度来看,当它试图寻找合适的函数时,两者都有以下签名:
Column
因此,template <typename T, template<typename, typename> class C, typename>
void f(const C<T>& coll);
的第二个定义实际上是重新定义。
考虑一个最小的例子:
f
编译器如何确定要调用的template<typename = void>
void f() {}
template<typename = char>
void f() {}
// ...
f<>();
?
您的代码中或多或少会发生相同的情况。
将f
移至返回类型,它将按预期工作
在这种情况下,由于错误(如sfinae表达式所预期的那样),替换将排除两个定义中的一个。
答案 1 :(得分:1)
为什么需要SFINAE?一个简单的过载就足够了!
template <typename T>
void f(const std::vector<T>& coll)
{
std::cout << "vector" << std::endl;
}
template < typename T>
void f(const std::list<T>& coll)
{
std::cout << "list" << std::endl;
}
int main()
{
std::vector<int> c1{ 1, 2, 3 };
std::list<int> c2{ 1, 2, 3 };
f(c1);
f(c2);
}
如果您真的想使用SFINAE(在这种情况下毫无意义),您可以使用以下方法修复您的定义:
template
<
typename T,
template<typename, typename = std::allocator<T>> class C,
typename std::enable_if_t
<
std::is_same<std::list<T>, C<T>>::value
>* = nullptr
>
void f(const C<T>& coll);
为什么你的定义不起作用可以在这里找到: SFINAE working in return type but not as template parameter