我正在尝试创建一个可以接受(并且可以消除歧义)字符串文字的类。在搜索此问题时,提供的解决方案是创建一个只能接受char指针的“holder”类:
template< typename char_t >
class String
{
struct holder_t
{
const char_t* s;
holder_t( const char_t* s ) : s(s) {}
holder_t( char_t* s ) : s(s) {}
};
public:
// Construct from string literal
template< size_t S >
String( const char_t (&str)[S] )
{
std::cout << "String Literal: " << str;
}
// Construct from char pointer
String( holder_t h )
{
std::cout << "Char Pointer: " << h.s;
}
};
最大的想法是你永远不必显式创建这个类的实例,它应该通过隐式转换来实现:
void StringFoo( String<char> s )
{
}
但是这会导致char指针的编译错误,为什么隐式转换不起作用?
int main()
{
// Works!
StringFoo( "literal" );
// error C2664: 'StringFoo' : cannot convert parameter 1 from 'const char *' to 'String<char_t>'
// with [ char_t=char ]
// No constructor could take the source type, or constructor overload resolution was ambiguous
StringFoo( (const char*)"const char ptr" );
// Works!
StringFoo( String<char>((const char*)"const char ptr") );
// error C2664: 'StringFoo' : cannot convert parameter 1 from 'char *' to 'String<char_t>'
// with [ char_t=char ]
// No constructor could take the source type, or constructor overload resolution was ambiguous
StringFoo( (char*)"char ptr" );
// Works!
StringFoo( String<char>((char*)"const char ptr") );
return 0;
}
这只是一个简单的无意义的例子;在我的真实代码中,我创建了一个将保存字符串哈希值的类。
如果传递字符串文字并在运行时计算(如果传递了char指针),则应在编译时生成散列。
然而,这应该对刚刚传递字符串的用户完全透明,哈希是自动完成的。
答案 0 :(得分:1)
要从字符串文字到String
,需要进行两次用户定义的转换 - 一次转换为holder_t
,另一次转换为String
。但是重载决策只允许你为每个参数进行一次这样的转换。
答案 1 :(得分:1)
代码无法使用指针的原因是它需要两个版本(char const*
到holder
和holder
到String
。但是,隐式转换会做最多一次转换。
出于您描述的目的,我认为您可以合理地区分char const(&)[N]
和char const*
:因为您总是想要计算哈希值而只是让它成为{{1}在可能的情况下,使constexpr
引用的版本应该成功。