c++ - 为什么在没有模板声明编译的情况下包含在模板类中使用模板参数的友元函数的实现?

标签 c++ syntax compilation friend-function template-function

给定以下代码。

#include <iostream>
template<typename T>
class Foo 
{
public:
    Foo(const T& value = T());

    friend Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs)
    {
    // ...
    }
    friend std::ostream& operator<< (std::ostream& o, const Foo<T>& x)
    {
    // ...
    }
private:
    T value_;
};

编译器可以毫无问题地编译两个具有模板参数的友元函数,而无需使用以下语法

template <typename T>
friend Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs)

friend Foo<T> operator+ <>(const Foo<T>& lhs, const Foo<T>& rhs)

friend Foo<T> operator+ <T>(const Foo<T>& lhs, const Foo<T>& rhs)

因为它们已由模板类本身的实现定义。

编译器如何在不包含模板声明的情况下使用模板参数编译这些友元函数?为什么只在类中实现它们就足够了?

我从 here 了解到这个概念在“为什么我使用模板 friend 时会出现链接器错误?”部分下

最佳答案

这两个选项,带和不带 template<class T> , 做一些稍微不同的事情。

当你介绍一个 friend以这种方式运行,您可以通过 ADL(参数相关查找)才能访问的方式在封闭的命名空间中引入它。

template<class T>引入函数模板,不引入函数模板的引入实际函数。

所以这样:

template<class T>
struct foo {
  friend void bar(foo<T>){}
};

表示当foo<int>存在,函数 bar(foo<int>)被 build 。然后 foo<double>创建bar(foo<double>) .

这些中的每一个 bar s 不是 template功能。它们是 eaxh 一个具有固定签名的函数,一个新的重载,类似于你写的

void bar(foo<char>){}

foo之后.异常(exception)情况是 friend bar只能通过 ADL 找到,这改变了冲突和重载解决的工作方式。

现在这个:

template<class T>
struct foo {
  template <typename X>
  friend void bar(foo<X>){}
};

创建一个 template bar对于 foo 的每个实例.这些并不冲突,因为它们只能通过 ADL 找到。唯一可以找到的是 T 所在的那个匹配X (在这种情况下——如果参数更多,它可能会有所不同)。

template 很少是个好主意版本,根据我的经验。

关于c++ - 为什么在没有模板声明编译的情况下包含在模板类中使用模板参数的友元函数的实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29504265/

相关文章:

c++ - undefined reference

c++ - 提升用户输入功能的测试用例

c++ - 为什么我们在传递动态二维数组时不需要列数?

powershell - 如何使用点符号字符串从 PSObject 获取子对象

python - 字符串创建 : Differences between two syntaxes ' ' and ""?

iphone - 是否可以使用编译器生成 .o 文件,然后使用另一个编译器链接它们?

c++ - 如何在 Windows 中编译 nDPI 库自带的 ndpiReader.c?

c++ - 嵌入式 Windows XP 中的网络接口(interface)设置

c++ - 使用 C/C++ 获取错误消息 MSB6006 错误代码 2

syntax - Scala 中符号文字的一些示例用例有哪些?