【问题标题】:Variadic template function name lookup fails to find specializations可变模板函数名称查找无法找到特化
【发布时间】:2015-07-25 10:08:30
【问题描述】:

我正在尝试编写一个字符串连接函数,该函数利用我的 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, "." )

返回

这是 dMap[500][500]: 112true5。

"true" 是 toString 返回的内容,如果将字符串文字传递给它。调试确认第二个字符串文字被泛型 String c(T a, Args... args) 捕获,但不是第一个或第三个,由特化处理。

这似乎与Selecting string literal type for template specialization 中提到的问题有关,但是更改我的模板参数声明与该解决方案中建议的inline String c( const char (&amp;s) [N], Args... args ) 相匹配,会导致第一个参数被专用模板捕获,而不是第二个或第三个参数.这里发生了一些不寻常的事情,我无法弄清楚它是什么。

【问题讨论】:

  • 名称查找问题。特别是,当定义第一个(通用)可变参数版本时,后面的两个重载不在作用域内,对c 的非限定查找将不会考虑它们。声明它们,然后定义它们。
  • 顺便提一下,Stringconst char * 的单参数版本不应该是特化。

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


【解决方案1】:

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&lt;&gt; 并改用重载。正如现在所写的那样,U::c(""); 不会按照您希望的方式运行。

Demo.

【讨论】:

  • 解决了这个问题。你对单论点的看法也是对的,我想我被困在了模板的思维模式中,没有意识到那些并不完全正确。非常感谢,它很有意义并且现在可以正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多