Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambda inside subscript iterator

Having a lambda in a subscript operator seems to be not working for g++ and clang.

Is this an implementation error or a "unhappy" rule in c++ standard?

Example:

class A
{   
    public:
        template<typename T> void operator[](T) {}
        template<typename T> void operator()(T) {}
};  

int main()
{   
    A a;
    a[ [](){} ];    // did not compiler: see error message
    a( [](){} );    // works as expected
} 

Error:

main.cpp:13:6: error: two consecutive '[' shall only introduce an attribute before '[' token
     a[ [](){} ];
      ^   
main.cpp:13:15: error: expected primary-expression before ']' token
     a[ [](){} ];

I know that attributes starts with "[[" but I am wondering that "[ [" ( with one or more white spaces ) also works like:

 void func( int x [ [gnu::unused] ] ) {} // compiles fine! :-(
like image 977
Klaus Avatar asked Sep 09 '16 12:09

Klaus


3 Answers

You have to enclose the lambda in parentheses. Otherwise the compiler considers two [[ as introducing an attribute.

A similar problem can occur with using operator delete. For example you have to write

delete ( [] { return ( new int() ); }() );

or

delete [] ( [] { return ( new int[10] ); }() );

that is you have to enclose the lambda in parentheses.

like image 127
Vlad from Moscow Avatar answered Oct 20 '22 21:10

Vlad from Moscow


This is covered in [dcl.attr.grammar]. Having two consecutive [ is an attribute, so you'll have to wrap in parantheses or do something else to make your intent clear:

Two consecutive left square bracket tokens shall appear only when introducing an attribute-specifier or within the balanced-token-seq of an attribute-argument-clause. [ Note: If two consecutive left square brackets appear where an attribute-specifier is not allowed, the program is ill-formed even if the brackets match an alternative grammar production. —end note ] [ Example:

int p[10];
void f() {
  int x = 42, y[5];
  int(p[[x] { return x; }()]);   // error: invalid attribute on a nested
                                 // declarator-id and not a function-style cast of
                                 // an element of p.
  y[[] { return 2; }()] = 2;     // error even though attributes are not allowed
                                 // in this context.
  int i [[vendor::attr([[]])]];  // well-formed implementation-defined attribute.
}

—end example ]

like image 32
Barry Avatar answered Oct 20 '22 19:10

Barry


You can wrap the argument with parentheses

a[ ( [](){} ) ];
like image 37
max66 Avatar answered Oct 20 '22 19:10

max66