Why argument dependent lookup doesn't consider Foo::dynamicCast
, shouldn't it consider namespace Foo because the Base class is in this namespace?
#include <memory>
using namespace std;
namespace Foo
{
template<typename P, typename T> P*
dynamicCast(T* t)
{
return dynamic_cast<P*>(t);
}
class Base
{
public:
virtual ~Base() = default;
};
}
namespace Test
{
class Derived : public Foo::Base
{
};
}
shared_ptr<Foo::Base> b = make_shared<Test::Derived>();
auto d = dynamicCast<Test::Derived>(b.get());
In order to even understand that you have a function call with a template, and not a bunch of <
and >
operators, the compiler must know you have a function template; and in order to understand that, it must know what namespace to look it up in. And in order to know that, it must understand the namespaces of the function arguments. And in order to understand that it must know there are function arguments around. Which, as we have seen, depends on knowing that there's a function call to begin with. Which the compiler doesn't know until it finds a template declaration. See the problem?
Because of that, ADL is only ever considered if the postfix-expression in the function call is an unqualified-id. Which dynamicCast<Test::Derived>
is not <edit> only if dynamicCast
is known to be a template-name, which is determined during normal unqualified lookup, which doesn't look into the namespace where the template is declared.
As @T.C. observed, one can declare an unrelated function template named dynamicCast
in the global namespace in order to make ADL work.
</edit>
In a better world we would have an option to write template foo<whatever>
in any context and disambiguate the angle brackets. Maybe in C++20.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With