Vit*_*meo 6 c++ lambda language-lawyer fold-expression c++17
考虑以下代码段:
template <typename TF>
void post(TF){ }
template <typename... TFs>
struct funcs : TFs...
{
funcs(TFs... fs) : TFs{fs}... { }
void call()
{
(post([&]{ static_cast<TFs&>(*this)(); }), ...);
}
};
Run Code Online (Sandbox Code Playgroud)
g ++ 7.0无法编译,出现以下错误:
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)(); }), ...);
~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
删除post调用和lambda 使g ++编译fold表达式.
lambdas,fold表达式和模板函数调用之间的这种交互是否被标准禁止,或者这是一个gcc错误?
这是一个老的gcc bug.这是gcc模板处理比MSVC更糟糕的少数情况之一.羞愧gcc.耻辱.
有时可行的解决方法是使用标记和包扩展.
template<class T>struct tag_t{using type=T; constexpr tag_t(){};};
template<class T>constexpr tag_t<T> tag{};
template<class Tag>using type_t=typename Tag::type;
#define TAG2TYPE(...) type_t<decltype(__VA_ARGS__)>
// takes args...
// returns a function object that takes a function object f
// and invokes f, each time passing it one of the args...
template<class...Args>
auto expand( Args&&...args ) {
return [&](auto&& f)->decltype(auto) {
using discard=int[];
(void)discard{0,(void(
f( std::forward<Args>(args) )
),0)...};
};
}
template <typename TF>
void post(TF){ }
template <typename... TFs>
struct funcs : TFs...
{
funcs(TFs... fs) : TFs{fs}... { }
void call() {
expand( tag<TFs>... )
([&](auto tag){
post(static_cast< TAG2TYPE(tag)& >(*this)());
});
}
};
Run Code Online (Sandbox Code Playgroud)
我们通过每次传递lambda来小心地避免在lambda的末尾扩展.相反,我们采用一组参数并将其扩展为一组lambda调用.
lambda获取作为标记传入的类型,然后我们将其转换回类型.
expand如果您通过临时表,请不要存储退货类型.
| 归档时间: |
|
| 查看次数: |
846 次 |
| 最近记录: |