使用fold表达式将参数包扩展为lambda - gcc vs clang

时间:2016-11-22 22:10:45

标签: c++ lambda language-lawyer c++17 fold-expression

考虑以下代码段:

template <typename TF>
void post(TF){ }

template <typename... TFs>
struct funcs : TFs...
{
    funcs(TFs... fs) : TFs{fs}... { }

    void call() 
    { 
        (post([&]{ static_cast<TFs&>(*this)(); }), ...); 
    }
};

clang++ 3.8+ successfully compiles the code

g++ 7.0 fails to compile出现以下错误:

prog.cc: In lambda function:
prog.cc:10:43: error: parameter packs not expanded with '...':
        (post([&]{ static_cast<TFs&>(*this)(); }), ...);
                   ~~~~~~~~~~~~~~~~~~~~~~~~^~
prog.cc:10:43: note:         'TFs'
prog.cc: In member function 'void funcs<TFs>::call()':
prog.cc:10:13: error: operand of fold expression has no unexpanded parameter packs
        (post([&]{ static_cast<TFs&>(*this)(); }), ...);
         ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

删除post调用和lambda makes g++ compile the fold expression

标准是否禁止lambdas,fold表达式和模板函数调用之间的这种交互,还是这是一个gcc bug?

2 个答案:

答案 0 :(得分:9)

这是old gcc bug。这是gcc模板处理比MSVC更糟糕的少数情况之一。羞愧gcc。羞。

有时可行的解决方法是使用标记和打包扩展。

expand

我们通过每次传递lambda来小心地避免在lambda的末尾扩展。相反,我们采用一组参数并将其扩展为一组lambda调用。

lambda获取作为标记传入的类型,然后我们将其转换回类型。

Live example

如果你传递临时类型,请不要存储/g的返回类型。

答案 1 :(得分:4)

这是一个众所周知的g ++错误(#47226),已于2011年报道。