c++ - C++ 模板的函数解析是如何完成的?

标签 c++ function templates overloading overload-resolution

让我困惑的代码贴在这里:

namespace ns1 {
    struct myStruct1 {};
    struct myStruct2 {};
}

namespace ns2 {
    template <typename T>
    constexpr int foo(T& x) {
        return 1;
    }

    // If the two functions below are switched, it returns 2 correctly
    template <typename T>
    constexpr int fooCaller(T& x) {
        return foo(x);
    }

    constexpr int foo(ns1::myStruct2& x) {
        return 2;
    }
}

// If the below is uncommented, it also returns 2 correctly
/*
namespace ns1 {
    constexpr int foo(myStruct2& x) {
        return 2;
    }
}
*/

int main() {
    ns1::myStruct1 struct1;
    constexpr int struct1Foo1 = ns2::foo(struct1);
    static_assert(struct1Foo1 == 1);
    constexpr int struct1Foo2 = ns2::fooCaller(struct1);
    static_assert(struct1Foo2 == 1);

    ns1::myStruct2 struct2;
    constexpr int struct2Foo1 = ns2::foo(struct2);
    static_assert(struct2Foo1 == 2);
    constexpr int struct2Foo2 = ns2::fooCaller(struct2);
    static_assert(struct2Foo2 == 2); // Assertion fails, returns 1 instead!
}

我正在尝试重载模板函数 (foo)。如果我没理解错的话,模板代码只会在调用函数时生成。到那时,应该已经声明了该函数的重载版本(如您在代码中所见)并且名称查找应该已经在该重载版本上进行了选择。

我确定已经定义了重载版本,因为 static_assert(struct2Foo1 == 1) 返回 True,这表明 foo(ns1::myStruct2&) 已定义。

另一个令人费解的事情是将重载版本放在 namespace ns1 中会导致模板函数选择重载版本。我知道这可能是由于 ADL 而发生的,但我不确定为什么 ADL 应该在同一个命名空间中直接重载时不起作用。

那么,当我将它放在同一命名空间中的模板声明下方时,为什么它没有选择重载版本?

最佳答案

从属名称的普通非限定查找仅考虑在模板定义上下文中找到的声明。因此,找不到 ns2 中的第二个 foo

依赖于参数的查找将考虑在定义或实例化上下文中找到的声明,但它只查找与参数关联的 namespace 和类,此处为 ns1。因此,将找到稍后在 ns1 中声明的 foo,但不会在 ns2 中找到。

关于c++ - C++ 模板的函数解析是如何完成的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51664782/

相关文章:

c++ - 为容器中的不同字符串类型实现编译时 "static-if"逻辑

c++ - 这个重新分配是否正确?

c - 同一个函数的两个不同参数却返回不同的结果?

javascript - 如何将参数传递给同一组件中的函数?

php - 如何使变量在模板中可用?

c++ - typedef 带有参数的模板化类

c++ - std::get_time 没有解析日期

c++ - glDrawElements 中的第 4 个参数是什么?

c++ - 为什么 emplace_hint 比插入 map 慢?

ios - 创建元组数组以调用函数但无法获得返回