Видны ли локальные функции-функции в лямбдах C ++ 0x? - PullRequest
12 голосов
/ 23 января 2010

Я столкнулся со странной проблемой. Следующий упрощенный код воспроизводит проблему в MSVC 2010:

template <typename T>
struct dummy
{
    static T foo(void) { return T(); }
};

int main(void)
{
    typedef dummy<bool> dummy_type;
    auto x = []{ bool b = dummy_type::foo(); };
    // auto x = []{ bool b = dummy<bool>::foo(); }; // works
}

typedef, который я создал локально в функции, кажется, не виден в лямбде. Если я заменю typedef на фактический тип, он будет работать как положено.

Вот еще несколько тестов:

// crashes the compiler, credit to Tarydon
int main(void)
{
    struct dummy {};

    auto x = []{ dummy d; };
}

// works as expected
int main(void)
{
    typedef int integer;

    auto x = []{ integer i = 0; };
}

У меня нет g ++, чтобы проверить это прямо сейчас. Это какое-то странное правило в C ++ 0x или просто ошибка в компиляторе?

Из приведенных выше результатов я склоняюсь к ошибке. Хотя сбой определенно является ошибкой.


На данный момент я подал два сообщения об ошибках .

Все приведенные выше фрагменты кода должны быть скомпилированы. Ошибка связана с использованием разрешения области в локально определенных областях. (Замечено dvide .)

А ошибка при сбое связана с ... кто знает. :)


Обновление

Согласно сообщениям об ошибках , они оба были исправлены в следующем выпуске Visual Studio 2010. (Хотя это не так; VS11 возможно.)

Ответы [ 4 ]

9 голосов
/ 23 января 2010

от n3000, 5.1.2 / 6,

лямбда-выражения составное утверждение дает function-body (8.4) функции оператор вызова, но для целей поиск имени (3.4),… составное заявление рассматривается в контекст лямбда-выражения.

Не удивительно, что локальный тип должен быть видимым.

3 голосов
/ 21 мая 2010

Функционально-локальные перечисления также не могут быть обнаружены лямбдами.

int main()
{   
    enum E {A, B, C};   
    auto x = [](){ int a = A; }; 
    //auto y = [](){ E a = A; }; // this will crash the compiler
}

ошибка C3493: «A» не может быть захвачен неявно, потому что не задан режим захвата по умолчанию

Следующее - это обходной путь, проблемный, может быть, хотя.

int main()
{   
    enum E {A, B, C};   
    auto x = [=](){ int a = A; };
    // typedef E F; 
    // auto y = [=](){ F a = A; }; // this compiles ok
}
2 голосов
/ 23 января 2010

Я подал два сообщения об ошибках.

Посмотрим, как оно пойдет. :)


Обновление

Обе ошибки были помечены как исправленные:

Мы ценим ваше мнение. Эта ошибка была замечена нами ранее, и мы исправили ее в следующем выпуске. Спасибо за использование продукта.

Спасибо
Ульзии Лувсанбат
Windows C ++ Team

Итак, поехали.

2 голосов
/ 23 января 2010

Это на самом деле не ответ на ваш вопрос, а просто дальнейшее изучение проблемы. Мне было интересно, есть ли у компилятора проблемы, связанные с типами , объявленными во вложенной области видимости, поэтому попытался:

#include <iostream>

template <typename Func>
void do_test(Func pFunc) {
}

template <typename T>
void test_trait(void) {
   class Something { public: int foo; };

   do_test ([] (T pX) {
      Something A; A.foo = 12;
   });
}

int main(void) {
    test_trait<int> ();
}

Здесь я просто пытаюсь создать локальный тип во внешней области и использовать его из лямбда-функции. Он не только не компилируется (с Visual Studio 2010, бета-версия 2), но также приводит к сбою компилятора с внутренней ошибкой C1001.

...