Видны ли локальные определения типов функций внутри лямбд C ++ 0x?
-
22-09-2019 - |
Вопрос
Я столкнулся со странной проблемой.Следующий упрощенный код воспроизводит проблему в 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 или просто ошибка в компиляторе?
Исходя из приведенных выше результатов, я склоняюсь к ошибке.Хотя сбой, безусловно, является ошибкой.
На данный момент я подал два заявления сообщения об ошибках.
Все приведенные выше фрагменты кода должны быть скомпилированы.Ошибка связана с использованием разрешения области в локально определенных областях.(Замечен двид.)
И ошибка сбоя имеет отношение к этому...кто знает.:)
Обновить
В соответствии с сообщения об ошибках, они оба были исправлены в следующем выпуске Visual Studio 2010.(Хотя, похоже, это не так;Возможно, VS11.)
Решение
Начиная с n3000, 5.1.2/6,
Составной оператор лямбда-выражения выдает тело функции (8.4) оператора вызова функции , но для целей поиска имени (3.4) ... составной оператор рассматривается в контекст лямбда-выражения.
Неудивительно, что локальный тип должен быть виден.
Другие советы
Функция-локальные перечисления также не могут быть обнаружены с помощью лямбд.
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
}
На самом деле это не ответ на ваш вопрос, а просто дальнейшее изучение проблемы.Мне было интересно, есть ли у компилятора проблемы, связанные с типы объявлено во внешней области видимости, так что попробовал это сделать:
#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.
Я отправил два сообщения об ошибках.
Посмотрим, как все пойдет.:)
Обновить
Обе ошибки были отмечены как исправленные:
Мы ценим ваши отзывы.Эта ошибка была замечена нами ранее, и мы исправили ее в следующем выпуске.Благодарим вас за использование продукта.
Спасибо,
Улзии Лувсанбат
Команда Windows C ++
Итак, поехали.