接上篇:
利用类型,做函数模板的“重载”-CSDN博客
比较两种模板的写法
为什么左边不可行:
注意,左边的写法的第二个模板参数,是默认参数的形式。为何这里采取了默认参数的形式呢,本意是想让编译器来走sfine的流程,用户不用指明具体的类型。但就是这一点让最后的编译失败
当编译到test451(1);时,实例化成了
??$test451@HH@@YAXH@Z,也就是void __cdecl test451<int,int>(int)
template <typename Sequence, typename=int>
void test451(Sequence x)
{
std::cout << "1" << std::endl;
}
当编译到test451(1.0);时,按理说应该生成:void __cdecl test451<double,double>(double)
template <typename Sequence, typename=double>
void test451(Sequence x)
{
std::cout << "1" << std::endl;
}
但可能编译器不这么想,却给了一个“error C2995: “void test451(Sequence)”: 函数模板已经定义”的编译错误。明明void __cdecl test451<int,int>(int)和void __cdecl test451<double,double>(double)并不一样啊。
用C++ Insights分析
祭出C++ Insights吧,让它来分析分析下面的代码,看能否给出更多信息:
#include <cstdio>
#include <iostream>
#include <type_traits>template <typename Sequence, typename=typename std::enable_if<std::is_same<Sequence, int>::value, int >::type>void test451(Sequence x)
{std::cout << "1" << std::endl;
}template <typename Sequence, typename =typename std::enable_if<std::is_same<Sequence, double>::value, int >::type >void test451(Sequence x)
{std::cout << "1" << std::endl;
}template <typename Sequence, typename =typename std::enable_if<std::is_same<Sequence, std::wstring>::value, int >::type >void test451(Sequence x)
{std::cout << "1" << std::endl;
}int main()
{test451(1);test451(1.0);std::wstring str;test451(str);
}
给出的结论如下:
/home/insights/insights.cpp:13:5: error: template parameter redefines default argument
13 | typename std::enable_if<std::is_same<Sequence, double>::value >::type>
| ^
意思是,在实例化double的情况的时候,提示默认参数被重定义了。
/home/insights/insights.cpp:6:5: note: previous default template argument defined here
6 | typename std::enable_if<std::is_same<Sequence, int>::value >::type>
| ^
之前实例化的在这里。(int版本)
/home/insights/insights.cpp:14:10: error: redefinition of 'test451'
14 | void test451(Sequence x)
| ^
/home/insights/insights.cpp:7:10: note: previous definition is here
7 | void test451(Sequence x)
| ^
double版本的test451重新定义了int版本的test451。(所以报错)
果然是默认参数的问题。用int实例化的时候,默认参数是int,
/home/insights/insights.cpp:13:5: error: template parameter redefines default argument13 | typename std::enable_if<std::is_same<Sequence, double>::value, int >::type >| ^
/home/insights/insights.cpp:6:5: note: previous default template argument defined here6 | typename std::enable_if<std::is_same<Sequence, int>::value, int >::type>| ^
/home/insights/insights.cpp:14:10: error: redefinition of 'test451'14 | void test451(Sequence x)| ^
/home/insights/insights.cpp:7:10: note: previous definition is here7 | void test451(Sequence x)| ^
/home/insights/insights.cpp:28:5: error: no matching function for call to 'test451'28 | test451(1);| ^~~~~~~
/home/insights/insights.cpp:14:10: note: candidate template ignored: requirement 'std::is_same<int, double>::value' was not satisfied [with Sequence = int]14 | void test451(Sequence x)| ^
/home/insights/insights.cpp:29:5: error: no matching function for call to 'test451'29 | test451(1.0);| ^~~~~~~
/home/insights/insights.cpp:14:10: note: candidate template ignored: substitution failure [with Sequence = double, $1 = typename std::enable_if<std::is_same<double, double>::value, int>::type]14 | void test451(Sequence x)| ^
/home/insights/insights.cpp:32:5: error: no matching function for call to 'test451'32 | test451(str);| ^~~~~~~
/home/insights/insights.cpp:14:10: note: candidate template ignored: requirement 'std::is_same<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>, double>::value' was not satisfied [with Sequence = std::wstring]14 | void test451(Sequence x)| ^
5 errors generated.
Error while processing /home/insights/insights.cpp.