Kla*_*aus 10 c++ variadic-templates c++11
我想问一下以下代码是否有效.
我想知道在一个表达式中多次扩展参数包的可能性.
#include <iostream>
#include <tuple>
class ExpandWithConstructor
{
public:
template <typename ... T>
ExpandWithConstructor( T... args) { }
};
template <typename T>
int PrintArgs( T arg )
{
std::cout << arg << ", ";
return 0;
}
template <typename Head, typename ... T>
class DebugPrinter: public DebugPrinter<T...>
{
public:
DebugPrinter() { }
template< typename ...Y>
DebugPrinter( Y ... rest )
{
std::cout << "Construction of: " << __PRETTY_FUNCTION__ << " Values: " ;
ExpandWithConstructor{PrintArgs( rest)...};
std::cout << std::endl;
}
};
template <typename Head>
class DebugPrinter< Head >
{
public:
};
template <typename ... T>
class TypeContainer: public std::tuple<T...>
{
public:
TypeContainer(T... args):std::tuple<T...>(args...){};
};
template <typename... T1> class CheckVariadic;
template <typename... T1, typename ...T2>
class CheckVariadic< TypeContainer<T1...>, TypeContainer<T2...>> :
public DebugPrinter< T1, T2, T1...>...
{
public:
CheckVariadic( T1... args1, T2... args2, T1... args3): DebugPrinter< T1, T2, T1...>(args1, args2..., args1)... {}
};
int main()
{
CheckVariadic< TypeContainer<int,float>, TypeContainer<char, void*>> checkVariadic1{ 1,2.2,'c',(void*)0xddddd,5,6.6,};
}
Run Code Online (Sandbox Code Playgroud)
如您所见,代码使用:DebugPrinter <T1,T2,T1 ...> ...
如果T1用"int,float"给出,T2是"char,void*",它扩展为
DebugPrinter< T1, T2, int, float>...
Run Code Online (Sandbox Code Playgroud)
扩展到
DebugPrinter< int, char, int, float>
DebugPrinter< float, void*, int, float>
Run Code Online (Sandbox Code Playgroud)
同样的扩展与:
DebugPrinter< T1, T2, T1...>(args1, args2..., args1)...
Run Code Online (Sandbox Code Playgroud)
代码用clang3.3编译,但不用gcc4.8.1编译,所以我想询问代码是否有效.
更新:gcc 7.2仍然没有编译代码.
是的,您的代码完全有效。包扩展由模式和省略号组成,并且可以出现在另一个包扩展的模式中。在标准的 \xc2\xa714.5.3/5 段中,您会发现:
\n\n\n\n\n[...] 参数包名称的外观仅由最内层的封闭包扩展来扩展。包扩展的模式应命名一个或多个未由嵌套包扩展扩展的参数包;[...]
\n
包扩展可以在 \xc2\xa714.5.3/4 中提到的任何上下文中使用。鉴于你的例子:
\n\nDebugPrinter< T1, T2, T1...>...\n
Run Code Online (Sandbox Code Playgroud)\n\n两个包扩展均有效。第一个的上下文是 a template-argument-list
while,第二个出现在 a 中base-specifier-list
。
标准文本提供的示例:
\n\ntemplate<class ... Args>\nvoid g(Args ... args) { // OK: Args is expanded by the function\n // parameter pack args\n f(const_cast<const Args*>(&args)...); // OK: \xe2\x80\x9cArgs\xe2\x80\x9d and \xe2\x80\x9cargs\xe2\x80\x9d are expanded\n f(5 ...); // error: pattern does not contain any\n // parameter packs\n f(args); // error: parameter pack \xe2\x80\x9cargs\xe2\x80\x9d is not\n // expanded\n f(h(args ...) + args ...); // OK: first \xe2\x80\x9cargs\xe2\x80\x9d expanded within h,\n // second \xe2\x80\x9cargs\xe2\x80\x9d expanded within f\n}\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
2881 次 |
最近记录: |