可变参数模板函数名称查找无法找到特化

时间:2015-05-13 22:38:03

标签: c++ string templates c++11 variadic-templates

我正在尝试编写一个字符串连接函数,该函数利用我的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}}中建议的那些匹配,导致第一个参数被专用模板捕获,但不是第二或第三。这里发生了一些不寻常的事情,我无法弄清楚它是什么。

1 个答案:

答案 0 :(得分:4)

template<typename T, typename... Args>
inline String c(T a, Args... args)
{
    return Ogre::StringConverter::toString( a ) + c(args...);
}

cc(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("");将不会按照您希望的方式运行。

Demo