====== 2012.12.11 - lambdas vs. variadic templates ====== 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 {{:blog:2012:12:11:example_handler.cpp|example handler program}} follows: template 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; }; ===== problem ===== it worked like a charm for all of the cases, except for one -- the call with the [[wp>variadic templates]]. in GCC 4.5 nor 4.7 variadic template parameters cannot be unpacked within the lambda body. namely this {{:blog:2012:12:11:lambda_vs_vartempl.cpp|example code}} does not compile, while it should: template void g(A...a) { std::cout << sizeof...(A) << std::endl; } template void f(A...a) { auto l = [&]{ g(a...); }; // (clan)g++ Oops... :/ l(); } ===== compilers ===== 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 ...)::::__a’ lambda_vs_vartempl.cpp:13:26: error: unable to deduce ‘auto’ from ‘’ 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 ===== final remarks ===== the good news, that lambda vs. variadic templates bugs are already reported [[http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226|1]] [[http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41933|2]]. the bad news is both are already at least 2 years old... [[http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226#c2|gcc 4.8 is said not to fix this]] as well. [[wp>C++11]] is complex, after all... ;)