3

I did not find this question in SO. If it is a duplicate please refer to the answer and close this question.

Can a C++11 lambda function have a variable parameter list?

auto displayMessage = [objectLog] (const char * sFormat, ...) {
     ...
}
Piotr Skotnicki
  • 43,267
  • 7
  • 101
  • 142
Peter VARGA
  • 4,692
  • 3
  • 27
  • 58

3 Answers3

3

Yes, the grammar allows it, and nothing forbids it.

A lambda-declarator is defined in 5.1.2 [expr.prim.lambda] as:

lambda-declarator:
    ( parameter-declaration-clause ) mutableopt exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt

And a parameter-declaration-clause is defined in 8.3.5 [dcl.fct] as:

parameter-declaration-clause:
    parameter-declaration-listopt ...opt
    parameter-declaration-list , ...

Also, G++, Clang and EDG all accept it without problems.

Under the hood, a C++11 lambda generates closure type with an operator() member function, and there is no reason that function can't have ..., e.g. this lambda expression:

auto l = [](int, ...) { }

generates a type like this:

struct unnamed_closure_type {
  void operator()(int, ...) const { }
};

which is perfectly valid C++.

Jonathan Wakely
  • 153,269
  • 21
  • 303
  • 482
  • 2
    In fact, Clang won't allow you to use `va_start` in such lambda, it's a known bug (https://llvm.org/bugs/show_bug.cgi?id=19617) – Anton Savin Mar 18 '15 at 13:55
2

It was easier than I thought and as meant before nothing forbids it.

I must admit I could have tried it before but I am a C++ beginner and therefore I thought it is more complicated. Here is a code for a lambda function with variable parameter list. This lambda function is used for internal logging - either directly to stdout or to a file.

auto displayMessage = [objectLog] (const char * sFormatString, ...)
{
    char sMessage [MAX_LOG_LINE_LENGTH];
    va_list vArgPtr;
    va_start(vArgPtr, sFormatString);

    vsnprintf(sMessage, sizeof(sMessage), sFormatString, vArgPtr);
    // EDIT: according to Jonathan Wakely's comment - added va_end()...
    va_end(vArgPtr);

    if ( objectLog )
    {
        objectLog->insertLogEntry("%s", sMessage);
    }
    else
    {
        printf("%s", sMessage);
    }
};
Peter VARGA
  • 4,692
  • 3
  • 27
  • 58
0

I just tried with Apple LLVM 6 (LLVM 3.5svn) and it compiled just fine. I guess there's nothing very different from regular function calls here, with the only forbidden thing being the use of the auto keyword.

sansuiso
  • 8,519
  • 1
  • 36
  • 55