Общая лямбда против универсальной функции дает другое поведение - PullRequest
14 голосов
/ 27 марта 2019

Возьмем следующий код в качестве примера

#include <algorithm>

namespace baz {
    template<class T>
    void sort(T&&){}
}

namespace boot {
    const auto sort = [](auto &&){};
}

void foo (){
    using namespace std;
    using namespace baz;
    sort(1);
}

void bar(){
    using namespace std;
    using namespace boot;
    sort(1);
}

Я ожидал, что, поскольку foo скомпилировано, то bar также скомпилируется.К моему удивлению, foo компилируется правильно, а bar имеет проблему с неоднозначным вызовом функции sort.Я делаю что-то нелегальное здесь или это правильно, как должен вести себя компилятор?Если так, то почему это так отличается?Я думаю, что универсальная лямбда может рассматриваться как синтаксический сахар для универсальной функции.

живой пример

1 Ответ

16 голосов
/ 27 марта 2019

Проблема здесь не в том, что вызов sort неоднозначен, а в том, что имя sort неоднозначно. Поиск имени происходит до разрешения перегрузки.

Я считаю, что соответствующий раздел [basic.lookup] / 1 , в частности

[& hellip;] Объявления, найденные при поиске имени, должны либо обозначать одну и ту же сущность, либо все должны обозначать функции или шаблоны функций; в последнем случае декларации образуют набор перегруженных функций ([over.load]). [& Hellip;] * * 1 010

В вашем случае имя sort обозначает как объект boot::sort, так и набор перегруженных функций std::sort. Таким образом поиск имени не удается.

Ваш код действительно ничем не отличается от того, что вы написали, например

namespace baz {
    int a;
}

namespace boot {
    int a;
}

void foo() {
    using namespace baz;
    using namespace boot;
    a = 42;  // error: reference to 'a' is ambiguous
}

Попробуйте здесь ; сравните это с случаем, который на самом деле имеет неоднозначный вызов функции ; обратите внимание, что сообщение об ошибке такое же, как в вашем случае, в частности, ссылаясь на неоднозначность самого имени, а не на вызов функции.

...