few days ago at work i had a need to write error handling mechanism in multiple methods. the thing was, that the methods themselves were short (usually 2-3 lines), while error handling consisted of multiple catch-es and some logging. there was also an if(enabled) to be added at the beginning. well – excellent place for lambda! relevant fragment of the example handler program follows:
template<typename F> void errHandler(F f, bool enabled) { if(!enabled) return; try { f(); } catch(Exception1 const&) { // bla bla } catch(Exception2 const&) { // bla bla } } struct Example { void f1(std::string& str) const { auto l = [&](){ str+="?"; }; errHandler(l, enabled_); } void f2(std::string& str) const { auto l = [&](){ str+="!"; }; errHandler(l, enabled_); } bool enabled_ = true; };
it worked like a charm for all of the cases, except for one – the call with the variadic templates. in GCC 4.5 nor 4.7 variadic template parameters cannot be unpacked within the lambda body. namely this example code does not compile, while it should:
template<typename ...A> void g(A...a) { std::cout << sizeof...(A) << std::endl; } template<typename ...A> void f(A...a) { auto l = [&]{ g(a...); }; // (clan)g++ Oops... :/ l(); }
gcc 4.7 produces following error message on that:
lambda_vs_vartempl.cpp: In lambda function: lambda_vs_vartempl.cpp:13:19: error: parameter packs not expanded with ‘...’: lambda_vs_vartempl.cpp:13:19: note: ‘a’ lambda_vs_vartempl.cpp:13:20: error: expansion pattern ‘a’ contains no argument packs lambda_vs_vartempl.cpp: In instantiation of ‘void f(A ...) [with A = {double, double, int}]’: lambda_vs_vartempl.cpp:19:20: required from here lambda_vs_vartempl.cpp:13:26: error: using invalid field ‘f(A ...)::<lambda()>::__a’ lambda_vs_vartempl.cpp:13:26: error: unable to deduce ‘auto’ from ‘<expression error>’
but wait - there's more! clang++ 3.0-6 outputs this:
0 libLLVM-3.0.so.1 0x00007f92a16984bf 1 libLLVM-3.0.so.1 0x00007f92a1698909 2 libpthread.so.0 0x00007f92a0618030 3 clang 0x0000000000a3083d clang::Sema::DeduceAutoType(clang::TypeSourceInfo*, clang::Expr*, clang::TypeSourceInfo*&) + 29 4 clang 0x00000000008b001d clang::Sema::AddInitializerToDecl(clang::Decl*, clang::Expr*, bool, bool) + 1533 5 clang 0x00000000008042ee clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&, clang::Parser::ParsedTemplateInfo const&) + 1790 // ... 21 clang 0x00000000005c121f clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 319 22 clang 0x00000000005a9a8a clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 1114 23 clang 0x00000000005a17a4 cc1_main(char const**, char const**, char const*, void*) + 804 24 clang 0x00000000005a0154 main + 596 25 libc.so.6 0x00007f929f6edead __libc_start_main + 253 26 clang 0x00000000005a1329 Stack dump: // ... 1. lambda_vs_vartempl.cpp:13:27: current parser token ';' 2. lambda_vs_vartempl.cpp:12:1: parsing function body 'f' 3. lambda_vs_vartempl.cpp:12:1: in compound statement ('{}') clang: error: unable to execute command: Segmentation fault clang: error: clang frontend command failed due to signal 2 (use -v to see invocation) clang: note: diagnostic msg: Please submit a bug report to http://llvm.org/bugs/ and include command line arguments and all diagnostic information. clang: note: diagnostic msg: Preprocessed source(s) are located at: clang: note: diagnostic msg: /tmp/lambda_vs_vartempl-XSkQV6.ii
the good news, that lambda vs. variadic templates bugs are already reported 1 2. the bad news is both are already at least 2 years old… gcc 4.8 is said not to fix this as well. C++11 is complex, after all… ;)