c++argument-dependent-lookuppointer-conversion

Should static_pointer_cast calls be std:: qualified, or relied upon ADL?


static_pointer_cast resides in std namespace. Yet it takes pointers that are also in std namespace.

So both std:: qualified calls and unqualified calls are accepted.

Which one is the right, more idiomatic way to call static_pointer_cast?


Solution

  • Generally, if you know exactly which function you want to call, rather than allowing for customization, I would try to avoid ADL, implying avoiding unqualified calls.

    In this case it is not expected for a library to provide its own static_pointer_cast for shared_ptrs of their own type. You always want to call the std version. Calling std::static_pointer_cast directly guarantees that no other such static_pointer_cast will interfere.

    If you include e.g. a library that also declared some function named static_pointer_cast which happens to be viable for your call and is a better fit or more specialized in overload resolution than the std one, you may accidentally call it instead if you use an unqualified call.

    I think this is extremely unlikely to be a problem in the case of static_pointer_cast, because it is unlikely that a library will use that name in a way that the overload will be viable for a normal std::static_pointer_cast call and be at the same time a better match, all of it without realizing the implications.

    But for example for std::launder this seems to have happened in some code bases (the other way around) when C++17 was introduced and the std overload turned out to be a better match than the library one in an unqualified call with a standard library type as argument.

    If you look at for example C++ standard library implementations you will see that they follow this rule to avoid unqualified calls very strictly and use them only where the standard expects the user to be able to customize the call. Of course for non-library code especially this might not be as important of a consideration.


    But also note that prior to C++20, if there is no function template named static_pointer_cast found by usual unqualified lookup, then an unqualified call using an explicit template argument list (which are required for static_pointer_cast) will fail anyway. So before C++20 you don't really have the choice to use the unqualified call without a prior using declaration to import the function.