为什么这个ADL案例有效?

时间:2017-02-06 20:04:33

标签: c++ c++11 language-lawyer argument-dependent-lookup

find_type如何知道函数typemap的位置? 它收到的参数不是来自该命名空间,而是来自std命名空间!

#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, "");

此代码如何工作?允许这个的规则是什么?

我用GCC 6.3和clang 3.9.1进行了测试。

2 个答案:

答案 0 :(得分:19)

在C ++标准N4618§3.4.2[basic.lookup.argdep](2.2)

  

如果T是类类型(包括联合),则其关联的类是:类本身;它所属的类   会员,如果有的话;及其直接和间接基类。其关联的命名空间是最里面的   包含其关联类的名称空间。此外,如果T是类模板专业化,   其关联的命名空间和类还包括:与之关联的命名空间和类   为模板类型参数提供的模板参数的类型(模板模板除外)   参数);任何模板模板参数都是成员的名称空间;和班级   其中任何用作模板模板参数的成员模板都是成员。

typemap的参数为std::unique_ptr<test::Test>,因此名称空间test会被视为名称查找。

答案 1 :(得分:14)

  

它收到的参数不是来自该命名空间,而是来自std命名空间!

不是全部!

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

这是:

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

那里有一个test::,因此也会搜索名称空间test