2014-01-10 143 views
1

我目前正在尝试为显示不同值的功能的函数编写模板专门化。 我的代码是:如何创建C++模板?

#include <iostream> 
using namespace std; 
template <class T> 
T myfunc(T x) 
{ 
    return x*x; 
} 
template<> 
string myfunc<string>(string ss) 
{ 
    return (ss+ss); 
} 
int main() 
{ 
cout<<myfunc("test")<<endl; 
return 0; 
} 

编译失败:

错误C2784:“的std :: _ St​​ring_iterator < _Mystr>的std ::操作 +(_ String_iterator < _Mystr> :: difference_type,标准: :_String_iterator < _Mystr>)” :不能推导出模板参数为 '的std :: _ St​​ring_iterator < _Mystr>' 从 '的std :: string'

你能帮我发现问题到底在哪里吗?

+4

'“test”'不会被推断为'std :: string'。它的类型是'const char [5]'。 – chris

回答

5

您需要将函数传递给字符串,而不是char数组。尝试myfunc(string("test"))

扩展一点 - 调用函数时要使用哪种模板/模板特化的选择称为模板参数推导。

你想调用myfunc,但是测试类型是char [5](结尾为空字符)。因此模板参数被推断为char [5]。

通常,char []可以在调用完全专用函数(不是模板函数)时隐式转换为字符串(我相信这是弃用的)。这种隐式转换是因为,正如user1274223所指出的,std :: string有一个带签名字符串(const char *)的构造函数,并且此构造函数为而不是显式!当我们想假装c字符串(char *)很容易与cplusplus字符串(std::string)互换时,这是有帮助的,但是在这些类型的情况下它可能会造成混淆。

另一个解决方法是myfunc<string>("test"),因为这里的模板参数是直接传递的,而且char []可以隐式转换为

+1

用于包含字符串()构造。 “测试”被解释为一个常量字符数组,而不是一个字符串,所以这个调用是必要的。 – Alejandro

+0

谢谢你的明确解释,但不幸的是它有一个相同的错误。 – user3140486

+0

@ user3140486它为我着迷,请尝试#include 如果'+'运算符完全缺少命名空间 – user3125280

1

模板专业化是在这种情况下是不必要的,你应该只重载函数:

std::string myfunc(const std::string &ss) 
{ 
    return (ss+ss); 
} 

这样调用它作为myfunct("test")会工作。

对于为什么所有的函数模板特通常不usefu你可以看看香草萨特的文章Why Not Specialize Function Templates?

+0

是的,但我认为“测试”的目的是为OP检查参数正在推导他是怎么想的 – user3125280

+1

你应该提到std :: string有一个const char *的构造函数,它不是显式的,这就是为什么字符串文字将被转换为字符串。 – Alejandro

0

正如其他人已经说过的细节。 此外,我认为你需要

#include <string> 

,其中,用于字符串和字符串操作+本身宣布 你的错误是你的编译器尝试匹配所有其它运营商+中和失败。

+0

哦,这是正确的.thank的很多:) – user3140486