Сбой ADL при наличии лямбда-аргументов? - PullRequest
4 голосов
/ 28 марта 2012

Некоторое время назад я заметил, что в Visual C ++ 10 ADL дает сбой, когда хотя бы один из аргументов является лямбда-выражением.

std::vector<float> vec;
for_each(begin(vec), end(vec), [](float) {}); 

Выше не удается скомпилировать на VC ++ 10 и 11 (бета) (начало и конец находятся через ADL).Когда я преобразовываю лямбда-функцию в обычную бесплатную функцию, все работает так, как ожидалось.

Я однажды спросил в блоге Херба Саттерса, а также прочитал несколько постов по msdn connect, и обычные ответы были: это ошибка, мы еще не внедрили последний стандарт лямбд, который - в то время -было вполне понятно.Вещи еще не были в запеченном виде.На MS Connect также были неприятные комментарии о том, что это не будет решено для следующего выпуска, т.е. vc 11.

Мой вопрос: этот код ожидается для работы под C ++?11 стандарт?Я не могу понять это.Действительно ли мне нужно использовать префикс моего for_each и других алгоритмов с помощью std ::, когда я использую лямбды?Я почему-то подозреваю, что это поведение не изменится после выпуска vc ++ 11.

Ответы [ 2 ]

15 голосов
/ 28 марта 2012

Стандарт не гарантирует, что вы хотите, чтобы ..

Имея в виду следующее, мы можем легко понять, что ничто не гарантирует, что ADL будет работать в случаях, подобных примеру, приведенному в вашем посте.


  • std::begin (c) / std::end (c)

    Функции описаны в стандарте как цитата ниже:

    template <class C> auto begin(C& c) -> decltype(c.begin());
    template <class C> auto end(C& c) -> decltype(c.end());
    

    Хотя Container< ... >::iterator (который является типом возврата c.begin ()) является определяемым реализацией типом .

    Подробнее об этом можно прочитать в 24.5.6 Range Access и 23.3.6.1 / 2 шаблонном векторе (или любом другом шаблонном контейнере STL) .

  • [](){} - Лямбда-выражения

    Лямбда - это тип , определяемый реализацией , в стандарте ничего не говорится о том, что результирующий объект будет иметь тип, который находится под пространством имен std .

    Он может существовать практически везде, где захочет, при условии, что он подтверждает другие правила, установленные стандартом.



Слишком долго; Не читал

Типы которых std::begin / std::end / a lambda-expression не гарантируют, что будут ниже namespace std , поэтому ADL не гарантированный удар.

1 голос
/ 28 марта 2012

Это совершенно правильный код. Любой безошибочный компилятор сможет его скомпилировать. Но поскольку MSVC имеет ошибку и поэтому не может найти функцию через ADL, то, возможно, вам не следует полагаться на ADL, а вместо этого квалифицировать ее как std::, помогая компилятору найти функцию.

...