Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

argument dependent lookup not considered [duplicate]

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());
like image 517
José Avatar asked Mar 14 '23 01:03

José


1 Answers

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.

like image 66
n. 1.8e9-where's-my-share m. Avatar answered Apr 01 '23 03:04

n. 1.8e9-where's-my-share m.