7

I am using assertion macro from assert.h I have defined lambda to perform assertion checking.

int val1 = 0;
int val2 = 1;

const auto check = [val1,val2]()-> bool
{
    return val1 < val2;
};
// no error for this call
assert(check() && "Test is failed");

// no error for this call
assert([=]()-> bool
       {
           return val1 < val2;
       }() && "Test is failed");
//compile error for this call "too many arguments provided to function-like macro invocation"
assert([val1,val2]()-> bool
       {
           return val1 < val2;
       }() && "Test is failed");

why I am getting

too many arguments provided to function-like macro invocation

compile error for the case when I am using assert macro and defining lambda with more than one argument in the capture list?

T M
  • 3,195
  • 2
  • 31
  • 52

2 Answers2

14

The problem is the comma in the capture list.

The preprocessor has an extremely limited understanding of the C++ syntax, it mainly does trivial text substitution. If a comma is not between matching inner parenthesis (and not part of a token like a string literal of course), the preprocessor will treat it as a separator of arguments of the macro invocation.

So the preprocessor thinks you are invoking assert with the two arguments [this and the rest of the stuff behind the first comma, which yields the error.

You can fix this error by using an extra set of parenthesis:

int i = -7, j = 7;
assert(([i,j](){return i + j;}()));

For the standard lovers:

The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives,155 the behavior is undefined.

16.3/11 in N4140, emphasis mine.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • Baum mit Augen still one thing not clear, the argument of assert in asert.h is inside () `#define assert(e) \ (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)` – T M Mar 12 '16 at 13:22
  • 1
    @TM Those parens come too late, for the quote above, the parens and commas *before* the expansion are relevant, not those in the result. – Baum mit Augen Mar 12 '16 at 13:33
1

The preprocessor is very simple, it sees all commas as argument separators.

So you can't use a macro if you pass in anything with a comma as argument to the macro.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Joachim Pileborg why it is not throwing compile error for other commas in case of call with [=]? – T M Mar 12 '16 at 12:15
  • @TM To be brutally honest I don't think you're telling us the truth. The preprocessor have no concept or knowledge of actual C++ code or C++ syntax, the preprocessor only knows its own limited language, where all commas in a macro "call" are used as argument separators. Therefore I don't believe that code will work and not give you an error. – Some programmer dude Mar 12 '16 at 12:19
  • Joachim Pileborg but it works :) without any compile error I am using Xcode Version 7.2.1 (7C1002) – T M Mar 12 '16 at 12:25
  • It really does work. ;) http://coliru.stacked-crooked.com/a/8bacaff636efa183 Macros understand the "function call syntax", but not the lambda capture syntax. – Baum mit Augen Mar 12 '16 at 12:28
  • 1
    That's weird, works for me too in GCC 5.2.1. It *shouldn't* work though. The problem seems to be the comma in the capture list. I'll have to check the standard to see if they changed anything with C++11 to make the preprocessor more intelligent. – Some programmer dude Mar 12 '16 at 12:34
  • 2
    *"The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments."* 16.3/11 in N4140. So gcc seems to be correct. Was that not the case pre-C++XX? If so, for what XX? – Baum mit Augen Mar 12 '16 at 12:36