我正在尝试编写一个字符串连接函数,该函数利用我的3D库的字符串转换函数,使用可变参数模板实现。
如果将字符串(const char [] literal或std :: string)传递给它,则库的转换函数会表现异常。因为它实际上并不具备这些类型的功能,所以我想专门化模板将它们拉出来而不是通过转换器运行它们。即使转换器处理它们,优化也是一个很好的理由。
template<typename T>
inline String c(T a)
{
return Ogre::StringConverter::toString( a );
}
template<>
inline String c(String s)
{
return s;
}
template<>
inline String c(const char s[])
{
return s;
}
template<typename T, typename... Args>
inline String c(T a, Args... args)
{
return Ogre::StringConverter::toString( a ) + c(args...);
}
template<typename... Args>
inline String c(String s, Args... args)
{
return s + c(args...);
}
template<typename... Args>
inline String c( const char s[], Args... args)
{
return s + c(args...);
}
但是,当我编译我的程序时,字符串文字有时会通过const char []特化,并由基本的非特定模板处理。命令:
U::c( "This is dMap[500][500]: ", dMap[500][500], " and this is 5: ", 5, "." )
返回
如果字符串文字传递给它,那么这是dMap [500] [500]:112true5。
“true”就是toString返回的内容。调试确认第二个字符串文字是由通用String c(T a, Args... args)
捕获的,而不是由专业化处理的第一个或第三个字符串。
这似乎与Selecting string literal type for template specialization中提到的问题有关,但更改我的模板参数声明与该解决方案{@ 1}}中建议的那些匹配,导致第一个参数被专用模板捕获,但不是第二或第三。这里发生了一些不寻常的事情,我无法弄清楚它是什么。
答案 0 :(得分:4)
在
template<typename T, typename... Args>
inline String c(T a, Args... args)
{
return Ogre::StringConverter::toString( a ) + c(args...);
}
c
中c(args...)
的非限定名称查找是在模板定义上下文中执行的,这意味着它只发现到目前为止所声明的c
重载,并且找不到您的后来c
超载。 (使用定义和实例化上下文执行ADL,但在您的情况下,它看起来没有ADL。)
首先声明它们:
template<typename T, typename... Args>
inline String c(T a, Args... args);
template<typename... Args>
inline String c(String s, Args... args);
template<typename... Args>
inline String c( const char s[], Args... args);
在定义之前,可以找到所有三个重载。
顺便说一句,您不应该对单参数情况使用特化。删除template<>
并改为使用重载。正如现在所写,U::c("");
将不会按照您希望的方式运行。