朋友,模板,命名空间

Ant*_*ier 4 c++ templates friend c++17

我想要一个模板化的朋友功能.但是,我不知道如何让它以相同的方式工作,没有模板化的功能.这是一个示例代码

#include <iostream>

namespace ns{
struct Obj {
    friend void foo(Obj){std::cout << "no problem" << std::endl;}

    template<typename T>
    friend void bar(Obj){std::cout << "problem" << std::endl;}
};
}

int main() {
    ns::Obj obj;
    foo(obj); // Compile
    bar<int>(obj); // Not compile
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 8

在C++ 20之前,您需要教授bar作为模板名称的编译器,以便它知道<启动模板参数列表并且不是小于运算符:

template<char> void bar() = delete;

int main() {
    ns::Obj obj;
    foo(obj); // Compile
    bar<int>(obj); // Now compiles too
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,所有bar重载都必须是一个函数模板.签名无关紧要,只要它不能干扰过载分辨率; ()是一个很好的选择,因为根据定义,我们传递至少一个参数,因此不带参数的函数模板永远不可行.

或者,您可以重新设计从标记参数bar推断T:

template<class T>
struct type {};

namespace ns{
struct Obj {    
    // ...

    template<typename T>
    friend void bar(Obj, type<T>) { /* ... */ }
};
}
// ...

bar(obj, type<int>()); // OK
Run Code Online (Sandbox Code Playgroud)

在C++ 20中,编译器会假设bar在看到<名称和名称查找时找不到模板,因此您的代码将起作用.

  • "只要它没有击败你实际想要调用的超载"...... (4认同)