简体   繁体   English

可变参数模板函数名称查找无法找到专长

[英]Variadic template function name lookup fails to find specializations

I am attempting to program a string concatenation function which utilizes my 3D library's string conversion functions, implemented with a variadic template. 我正在尝试编写一个字符串连接函数,该函数利用我的3D库的字符串转换函数(通过可变参数模板实现)。

The library's conversion function behaves unusually if a string (either const char[] literal or std::string) is passed to it. 如果将字符串(const char []文字或std :: string)传递给该库,则该转换函数的行为会异常。 as it does not actually possess functions for those types, so I want to specialize the template to pull those out and not run them through the converter. 因为它实际上不具备这些类型的功能,所以我想专门针对模板进行提取,而不是通过转换器运行它们。 Optimization would be a good reason even if the converter handled them. 即使转换器进行了处理,优化也是一个很好的理由。

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...);
}

However, when I compile my program, string literals sometimes fall through the const char[] specialization and are handled by the base, unspecialized template. 但是,当我编译程序时,字符串文字有时会落入const char []专业化范畴,并由基本的非专业化模板处理。 The command: 命令:

U::c( "This is dMap[500][500]: ", dMap[500][500], " and this is 5: ", 5, "." )

returns 回报

This is dMap[500][500]: 112true5. 这是dMap [500] [500]:112true5。

"true" being what toString returns if a string literal is passed to it. “ true”是toString返回的内容,如果将字符串文字传递给它。 Debugging confirms that the second string literal is caught by the generic String c(T a, Args... args) , but not the first or third, which are handled by the specialization. 调试确认第二个字符串文字被通用String c(T a, Args... args)捕获,但不是由专业化处理的第一个或第三个字符串捕获。

This seems related to the problem mentioned in Selecting string literal type for template specialization , but changing my template parameter declaration match those suggested in that solution, inline String c( const char (&s) [N], Args... args ) , cause the first parameter to be caught by the specialized template, but not the second or third. 这似乎与在为模板特化选择字符串文字类型中提到的问题有关,但是更改我的模板参数声明与该解决方案中建议的匹配,即inline String c( const char (&s) [N], Args... args ) ,专用模板捕获的第一个参数,而不是第二个或第三个。 Something unusual is happening here and I cannot figure out what it is. 这里发生了不寻常的事情,我无法确定它是什么。

In

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

unqualified name lookup for c in c(args...) is performed in the template definition context, which means that it only finds overloads of c declared up to this point, and will not find your later c overloads. 不合格的名称查找cc(args...)模板定义背景下,这意味着它只能找到的重载执行c宣布了这一点,并不会发现你以后c过载。 (ADL is performed using both the definition and the instantiation contexts, but in your case it looks like there's no ADL.) (ADL是同时使用定义上下文和实例化上下文执行的,但在您的情况下,看起来好像没有ADL。)

Declare them all first: 首先声明它们:

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);

before you define them, so that all three overloads can be found. 在定义它们之前,可以找到所有三个重载。


Incidentally, you should not use specializations for the single-argument case. 顺便说一句,您不应该对单参数情况使用特殊化。 Delete the template<> and use overloads instead. 删除template<>并改用重载。 As written right now, U::c(""); 如目前所写, U::c(""); will not behave the way you want it to. 不会表现出您想要的方式。

Demo . 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM