gpt4 book ai didi

c++ - 为模板类重载友元运算符<<

转载 作者:太空宇宙 更新时间:2023-11-04 13:28:52 27 4
gpt4 key购买 nike

我现在已经在 StackOverflow.com 上阅读了几个关于我的问题的问题,但似乎没有一个能解决我的问题。或者我可能做错了......重载<<如果我把它变成一个内联函数,它就可以工作。但是我该如何让它在我的案例中发挥作用呢?

warning: friend declaration std::ostream& operator<<(std::ostream&, const D<classT>&)' declares a non-template function

warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning

/tmp/cc6VTWdv.o:uppgift4.cc:(.text+0x180): undefined reference to operator<<(std::basic_ostream<char, std::char_traits<char> >&, D<int> const&)'
collect2: ld returned 1 exit status

代码:

template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}

template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const;
classT operator=(const D<classT>& rhs);

friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};


int main()
{

int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);

cout << my_max(d1,d2) << endl;
return 0;
}

template <class classT>
ostream& operator<<(ostream &os, const D<classT>& rhs)
{
os << rhs.d;
return os;
}

最佳答案

这是常见问题之一,这些问题具有相似但不完全相同的不同方法。这三种方法的不同之处在于您声明谁是您的函数的友元——以及您如何实现它。

外向的人

将模板的所有实例声明为友元。这是您接受的答案,也是大多数其他答案的建议。在这种方法中,您不必要地打开您的特定实例 D<T>通过声明所有 friend operator<<实例化。即 std::ostream& operator<<( std::ostream &, const D<int>& )可以访问 D<double> 的所有内部结构.

template <typename T>
class Test {
template <typename U> // all instantiations of this template are my friends
friend std::ostream& operator<<( std::ostream&, const Test<U>& );
};
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& ) {
// Can access all Test<int>, Test<double>... regardless of what T is
}

内向者

仅将插入运算符的特定实例声明为友元。 D<int>应用于自身时可能喜欢插入运算符,但它不想与 std::ostream& operator<<( std::ostream&, const D<double>& ) 有任何关系.

这可以通过两种方式完成,最简单的方式是@Emery Berger 提出的,即内联运算符——出于其他原因,这也是一个好主意:

template <typename T>
class Test {
friend std::ostream& operator<<( std::ostream& o, const Test& t ) {
// can access the enclosing Test. If T is int, it cannot access Test<double>
}
};

在第一个版本中,您不是创建模板化的 operator<< ,而是 Test 的每个实例化的非模板函数模板。同样,差异很小,但这基本上等同于手动添加:std::ostream& operator<<( std::ostream&, const Test<int>& )当你实例化 Test<int> ,以及实例化时的另一个类似重载 Testdouble ,或任何其他类型。

第三个版本比较繁琐。无需内联代码,并使用模板,您可以将模板的单个实例声明为类的友元,而无需向所有其他实例开放:

// Forward declare both templates:
template <typename T> class Test;
template <typename T> std::ostream& operator<<( std::ostream&, const Test<T>& );

// Declare the actual templates:
template <typename T>
class Test {
friend std::ostream& operator<< <T>( std::ostream&, const Test<T>& );
};
// Implement the operator
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& t ) {
// Can only access Test<T> for the same T as is instantiating, that is:
// if T is int, this template cannot access Test<double>, Test<char> ...
}

利用外向的人

第三个选项与第一个选项之间的细微差别在于您对其他类(class)的开放程度。 外向 版本中的一个滥用示例是有人想要进入您的内部并执行此操作:

namespace hacker {
struct unique {}; // Create a new unique type to avoid breaking ODR
template <>
std::ostream& operator<< <unique>( std::ostream&, const Test<unique>& )
{
// if Test<T> is an extrovert, I can access and modify *any* Test<T>!!!
// if Test<T> is an introvert, then I can only mess up with Test<unique>
// which is just not so much fun...
}
}

关于c++ - 为模板类重载友元运算符<<,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32292593/

27 4 0
文章推荐: html - 将颜色移动到单独的 CSS 文件不起作用
文章推荐: html - 使用图像创建下拉菜单
文章推荐: jquery - IE10 - 需要将 CSS 光标更改为 "pointer"在 contenteditable
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com