6

Consider

// 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);
}

I'd've expected the unqualified call to static_pointer_cast to resolve to std::static_pointer_cast, because b, being a std::shared_ptr, should bring namespace std in using ADL.

Why doesn't it? I need to write std::shared_pointer_cast explicitly to make it work.

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90
  • 5
    Until C++20, ADL works only with function call syntax, specifying a template argument explicitly, ``, breaks ADL unless a compiler already knows that it's a template. – Evg May 27 '21 at 07:41
  • Consider the POV of the compiler: all it sees is `identifier <` which looks awfully like the beginning `x < 2`. So it's grammatically difficult unlike `identifier (args)` which can only be a function call or an `operator()(args)` call if `identifier` designates an object or a "functional cast"/construction of a temporary [both are essentially the same concept through different syntactic constructs: `std::string("")` is a cast (explicit type conversion) but `std::string()` is not] if `identifier` designates a type. – curiousguy Jun 01 '21 at 16:13

1 Answers1

3

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

Although a function call can be resolved through ADL even if ordinary lookup finds nothing, a function call to a function template with explicitly-specified template arguments requires that there is a declaration of the template found by ordinary lookup (otherwise, it is a syntax error to encounter an unknown name followed by a less-than character) (until C++20)

In C++20 mode your code compiles fine, demo: https://gcc.godbolt.org/z/b13q4hs68

Fedor
  • 17,146
  • 13
  • 40
  • 131