Variadic 模板函数名称查找无法找到特化
Variadic template function name lookup fails to find specializations
我正在尝试编写一个字符串连接函数,该函数利用我的 3D 库的字符串转换函数,通过可变参数模板实现。
如果将字符串(const char[] 文字或 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, "." )
returns
This is dMap[500][500]: 112true5.
"true" 是什么 toString returns 如果将字符串文字传递给它。调试确认第二个字符串文字被通用 String c(T a, Args... args)
捕获,但不是第一个或第三个,它们由专业化处理。
这似乎与 中提到的问题有关,但更改我的模板参数声明与该解决方案 inline String c( const char (&s) [N], Args... args )
中建议的匹配,导致第一个参数被专用模板捕获,但不是第二个或第三个。这里发生了一些不寻常的事情,我无法弄清楚它是什么。
在
template<typename T, typename... Args>
inline String c(T a, Args... args)
{
return Ogre::StringConverter::toString( a ) + c(args...);
}
c(args...)
中 c
的非限定名称查找是在模板定义上下文中执行的,这意味着它只查找到此为止声明的 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.
我正在尝试编写一个字符串连接函数,该函数利用我的 3D 库的字符串转换函数,通过可变参数模板实现。
如果将字符串(const char[] 文字或 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, "." )
returns
This is dMap[500][500]: 112true5.
"true" 是什么 toString returns 如果将字符串文字传递给它。调试确认第二个字符串文字被通用 String c(T a, Args... args)
捕获,但不是第一个或第三个,它们由专业化处理。
这似乎与 inline String c( const char (&s) [N], Args... args )
中建议的匹配,导致第一个参数被专用模板捕获,但不是第二个或第三个。这里发生了一些不寻常的事情,我无法弄清楚它是什么。
在
template<typename T, typename... Args>
inline String c(T a, Args... args)
{
return Ogre::StringConverter::toString( a ) + c(args...);
}
c(args...)
中 c
的非限定名称查找是在模板定义上下文中执行的,这意味着它只查找到此为止声明的 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.