请考虑以下示例。
#include <string>
template<class CharT, class Traits = std::char_traits<CharT >, class Allocator = std::allocator<CharT >>
void f(const std::basic_string<CharT, Traits, Allocator>& s) {
}
int main() {
f("Hello World!");
}
编译时,我得到了
不匹配的类型
‘const std::basic_string<_CharT, _Traits, _Alloc>’ and ‘const char []’
为什么编译器不能扣除“CharT”并转换为适当的basic_string<>
?我想f()只有一个签名对于存在转换为basic_string<>
的任何参数类型都有效,是否有解决此问题的方法?
答案 0 :(得分:6)
您正在将一个原始字符串传递给您的函数,该函数不是std::string
,而是一个字符数组,const char []
。
即使std::string
有一个获取char数组的构造函数,在模板argumment推导期间也不会应用隐式类型转换(确切地说就是你遇到的问题)。有关该主题的更多信息,请参阅this thread。
有两种可能的解决方案:
将std::string
而不是原始字符串传递给您的函数:
f( std::string( "hello" ) );
写一个函数的重载,它与原始字符串一起使用:
template<typename CHAR_T , std::size_t LENGHT>
void f( const CHAR_T (&string)[LENGTH] )
{
f( std::string( string ) ); //Just wrap the call to not duplicate code.
}
答案 1 :(得分:1)
你问的是要求编译器迭代每个basic_string<T>
,直到它确定只有一个T
匹配。或者,它可以反转可能的图灵完成过程以找出template
参数是什么。 template
这样的参数推导就是模式匹配:它接受参数,并将其与模式匹配,并简单地推导出类型。如果您需要更多,您需要告诉它如何反映从CharT
到basic_string<CharT,A>
构造函数的映射。使用C ++ 1y可以轻松实现概念精简,但您想要的机器类型仍然不存在。
到目前为止,最简单的解决方案是对char
和wchar_t
basic_string
s(实际函数,而不是template
s)进行两次重载,然后让它们调用template
泛型函数,就像你在CharT
明确传递的内容一样。
Fancier将涉及实际执行上述反转的代码,您可以从一组可接受的字符串中使用它,并检查可以构造哪些参数,断言只有一个选项,并推导{{1 }} 那样。虽然很有趣,但我怀疑这是值得的。
答案 2 :(得分:0)
这应该可以解决问题。
你正在为你的函数指定一个char数组,它应该得到std :: string。您需要使用构造函数来转换它们。
#include <string>
template<class CharT, class Traits = std::char_traits<CharT >, class Allocator = std::allocator<CharT >>
void f(const std::basic_string<CharT, Traits, Allocator>& s) {
}
int main() {
std::string str("Hello World!");
f(str);
}