Почему static_pointer_cast не работает с ADL, но требует явного std::`?

Рассмотреть возможность

      // https://godbolt.org/z/z5M9b9jzx
#include <memory>
#include <cassert>

struct B {};
struct D : B {};

int main() {
    std::shared_ptr<B> b = std::make_shared<D>();
    auto d = static_pointer_cast<D>(b);
    assert(d);
}

Я ожидал неквалифицированного звонка static_pointer_cast разрешить std::static_pointer_cast, так как b, быть std::shared_ptr, должны принести namespace std в использовании ADL.

Почему нет? Мне нужно написать std::shared_pointer_cast явно, чтобы заставить его работать.

2 ответа

Если вы не используете C++20 , правила поиска не позволят этого.

Согласно определению ADL, чтобы он работал, выражение, обозначающее функцию, должно быть неквалифицированным идентификатором (это нормативный термин). И пока это неквалифицированный идентификатор, это не так! Это идентификатор шаблона (опять же нормативный термин), который обозначает специализацию шаблона.

Вызов функции (и ADL) не вступает в игру до тех пор, пока не будет определено постфиксное выражение.

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

https://en.cppreference.com/w/cpp/language/adl

Хотя вызов функции может быть разрешен через ADL, даже если обычный поиск ничего не находит, для вызова функции шаблона функции с явно указанными аргументами шаблона требуется, чтобы было объявление шаблона, найденного обычным поиском (в противном случае это синтаксическая ошибка. встретить неизвестное имя, за которым следует символ «меньше»)(до C++20)

В режиме C++20 ваш код компилируется нормально, демонстрация: https://gcc.godbolt.org/z/b13q4hs68

Другие вопросы по тегам