Why this ADL case is working?
Asked Answered
A

2

19

How does find_type know where the function typemap is?
The argument it receives is not from that namespace, it's from the std namespace!

#include <type_traits>
#include <memory>

namespace lib {
    template<typename T>
    struct find_type {
        using type = decltype(typemap(std::declval<T>()));
    };
}

namespace test {
    struct Test {};
    auto typemap(std::unique_ptr<Test>) -> int;    
}

static_assert(std::is_same<int, lib::find_type<std::unique_ptr<test::Test>>::type>::value, "");

How can this code work? What is the rule allowing this?

I tested it with GCC 6.3 and clang 3.9.1.

Aphis answered 6/2, 2017 at 20:4 Comment(1)
The parameter type of the template parameter T from the struct find_type is std::unique_ptr<test::Test>. std::unique_ptr considers the test::Test template parameter for ADL, and thus, finds the typemap function in the test NSPackthread
C
19

In the C++ standard N4618 §3.4.2 [basic.lookup.argdep] (2.2)

If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the innermost enclosing namespaces of its associated classes. Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template arguments are members.

The argument of typemap is std::unique_ptr<test::Test>, so namespace test is considered for name look up.

Clough answered 6/2, 2017 at 20:18 Comment(0)
T
14

The argument it receives is not from that namespace, it's from the std namespace!

Not all of it!

using type = decltype(typemap(std::declval<T>()));

This is:

using type = decltype(typemap(std::declval<std::unique_ptr<test::Test>>()));

There's a test:: in there, so the namespace test is searched too.

Talkingto answered 6/2, 2017 at 20:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.