2016-09-09 59 views
9

Posiadanie lambda w operatorze podrzędnym wydaje się nie działać dla g ++ i clang.iterator indeksu lambda wewnątrz indeksu

Czy jest to błąd implementacyjny, czy "nieszczęśliwa" reguła w standardzie C++?

Przykład:

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 
} 

Błąd:

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[ [](){} ]; 

Wiem, że atrybuty zaczyna się od "[[", ale zastanawiam się, że "[[" (z jednym lub więcej spacji) również działa tak:

void func(int x [ [gnu::unused] ]) {} // compiles fine! :-(

Odpowiedz

4

ta jest pokryta [dcl.attr.grammar]. Posiadanie dwóch kolejnych [ jest atrybutem, więc będziesz musiał zawinąć w nawiasach lub zrobić coś innego, aby twój zamiar jasne:

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 ]

+1

A co oznacza "kolejne" z dodatkowymi białymi znakami lub bez nich? – Klaus

+1

@Klaus C++ nie jest wrażliwy na białe znaki. ">>" był wyjątkiem w tym, że był uważany za token, ale nie ma "[tokena. – Barry

+1

Wczoraj dowiedziałem się, że 'template <> double B :: var = 1.123; 'jest nieprawidłowe, ale' szablon <> double B :: var = 1.123; 'działa. Tylko biała spacja ... :-) – Klaus

6

Musisz zamknąć lambdę w nawiasie. W przeciwnym razie kompilator uznaje dwa [[ za wprowadzenie atrybutu.

Podobny problem może wystąpić przy użyciu operatora delete. Na przykład trzeba napisać

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

lub

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

to trzeba ująć lambda w nawiasach.

+0

wspaniale zobaczyć te ciekawych przykładów z innym kontekście. Dzięki – Klaus

1

Można owinąć argument z nawiasami

a[ ([](){}) ]; 
+0

Teraz pomysł, jak było tutaj :-): Miło zobaczyć obejście. Ale czy ktoś ma pomysł, który jest zgodny z normą? Naprawienie początku atrybutów na "[" usunie ten problem. Właśnie dlatego zapytałem, czy jest to złamana implementacja czy "pechowy" standard. – Klaus