Emi*_*son 8 lambda variadic-templates c++11
这段代码在Clang 3.5中运行正常:
#include <iostream>
#include <string>
void callFuncs() {}
template<typename Func, typename ...Funcs>
void callFuncs(const Func &func, const Funcs &...funcs)
{
func();
callFuncs(funcs...);
}
template<typename ...Types>
void callPrintFuncs()
{
callFuncs(([] { std::cout << Types() << std::endl; })...);
}
int main()
{
callPrintFuncs<int, float, double, std::string>();
}
Run Code Online (Sandbox Code Playgroud)
但是,在GCC 4.9中,我得到以下错误:
test.cpp: In lambda function:
test.cpp:16:54: error: parameter packs not expanded with '...':
callFuncs(([] { std::cout << Types() << std::endl; })...);
^
test.cpp:16:54: note: 'Types'
test.cpp: In function 'void callPrintFuncs()':
test.cpp:16:58: error: expansion pattern '<lambda>' contains no argument packs
callFuncs(([] { std::cout << Types() << std::endl; })...);
Run Code Online (Sandbox Code Playgroud)
那么,哪个编译器有bug,Clang或GCC?Clang行为至少对我来说是最有意义的.
gcc 在这里被破坏了。标准中有针对未扩展参数包的规则,但上述参数包是扩展的。
它在其所在的最内层语句结束后展开,但标准不要求参数包在每个语句结束时展开。
gcc 搞错了这一事实是可以理解的;天真地,你会认为参数包只能在一条语句内,而在语句末尾扩展失败是致命的。但是 lambda 允许您在语句中嵌套语句。
一种通用的解决方法是传入一个 lambda 并向其传入“标签”类型。
template<class T>struct tag_t{using type=T;};
template<class Tag>using type_t=typename Tag::type;
template<typename Func, typename ...Ts>
void callOnEachOf(Func&&func, Ts&&...ts)
{
using discard=int[];
(void)discard{0,((void)(
func(std::forward<Ts>(ts))
),0)...};
}
template<typename ...Types>
void callPrintFuncs()
{
callOnEachOf(
[](auto tag){
using Type=type_t<decltype(tag)>;
std::cout << Type() << std::endl;
},
tag_t<Types>...
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
365 次 |
| 最近记录: |