Левая скобка не соответствует должным образом при использовании лямбда внутри скобок, внутри функции шаблона

Используя Visual C++ 2013, следующий код выдает странную ошибку компиляции:

/// header.h
class Test
{
public:
    template <typename Func>
    void operator[](Func f)
    {
        f();
    }
};

template <typename T>
void funct()
{
    Test t;
    t[[](){; }];    // line 16 // The same error with t[ ([](){; }) ];
}

/// main.cpp
int main()
{
    funct<int>();
    // funct();
}

Ошибки:

1>c:\path\to\header.h(16): error C2958: the left bracket '[' found at 'e:\path\to\header.h(16)' was not matched correctly
1>c:\path\to\header.h(16): error C2059: syntax error : ']'
1>c:\path\to\header.h(17): error C2059: syntax error : '}'
1>c:\path\to\header.h(17): error C2143: syntax error : missing ';' before '}'


Эта ошибка не возникает, когда тело лямбда-функции не имеет никаких операторов:

template <typename T>
void funct()
{
    Test t;
    t[[](){ }];    // line 16 // No semicolon - No statement - No errors
}


Или когда функция не является шаблоном:

// Ordinary function - No errors
void funct()
{
    Test t;
    t[[](){; }];    // line 16
}


Я думаю, что нашел ошибку в этом компиляторе. Однако, если кто-нибудь знает способ написать это без ошибок и без использования переменной для хранения лямбда-функции, это было бы здорово.

1 ответ

Решение

VC++ правильно отклоняет этот код, но по неправильным причинам - это ошибка. Это плохо сформировано согласно [dcl.attr.grammar]/6:

Два последовательных маркера левой квадратной скобки должны появляться только при введении атрибута-спецификатора. [ Примечание: если две последовательные левые квадратные скобки появляются там, где спецификатор атрибута не разрешен, программа будет некорректной, даже если скобки соответствуют альтернативному производству грамматики. - примечание конца ] [ Пример:

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.
}

- конец примера ]

Поэтому попробуйте заключить лямбда-выражение в два паратеза следующим образом.

t[ ([](){; }) ];

Или пиши

auto&& closure = [](){; };
t[closure]; // move here if correct value category is desired
Другие вопросы по тегам