【问题标题】:operator<< overload for a member type in a template class in C++运算符<< C++模板类中成员类型的重载
【发布时间】:2016-06-08 13:14:57
【问题描述】:

在下面的代码中,我有一个带有成员类型(结构元素)的模板类。我想为那个成员类型重载运算符

如果有人能指出我哪里出错了,我将不胜感激?

include <iostream>
using namespace std;

// fwd decl
template<class T> class CC;

// operator<< overload template for member type CC<T>::Element
template<class T>
ostream& operator<<(ostream& os, const typename CC<T>::Element& elm) {
    return os << elm.val1 << "/" << elm.val2;
}

template<class T>
class CC
{
public:
    struct Element {    // type member
        int val1;
        int val2;
    };

    template<typename U>
    friend ostream& operator<<(ostream& os, const typename CC<U>::Element& elm);
};

int main() {
    CC<int>::Element elm{0,0};
    cout << elm << endl;     // does not compile due to this!
}

【问题讨论】:

    标签: c++ templates operator-overloading type-members


    【解决方案1】:

    模板参数不能从嵌套实体中推导出来(简短的解释:对于不同的模板实例,类型可能是接缝的)。也就是声明

    template<typename U>
    ostream& operator<<(ostream& os, const typename CC<U>::Element& elm);
    

    永远不会考虑是否为friend,因为无法推断出U 类型。您可以通过将 friend 运算符设为非模板来解决此问题:

    // ...
    friend ostream& operator<<(ostream& os, const Element& elm) { ... }
    // or
    friend ostream& operator<<(ostream& os, const CC<T>::Element& elm) { ... }
    // ...
    

    不过,该函数需要在其声明中实现。

    【讨论】:

    • 感谢您抽出宝贵时间。我已经尝试了您的两个建议,但代码仍然无法编译。我收到此错误:undefined reference to `operator::Element const&)'
    • 划掉我之前的评论。我的错。我应该按照您提到的那样编写实现,但我没有。再次感谢。
    【解决方案2】:

    你的问题是在下面的代码中

     ostream& operator<<(ostream& os, const typename CC<T>::Element& elm) {
    

    Element 处于非推断上下文中。结果,不能推导出模板参数。而且由于使用显式模板参数调用operator&lt;&lt; 会非常难看(如果可能的话),我建议更改整体编码模式。

    例如,可以将elm 推导出为模板参数,比如

    template<typename E>
    friend ostream& operator<<(ostream& os, const E& elm);
    

    然后使用专门的结构从 E 中提取实际的U

    【讨论】:

    • 请注意,此函数模板在概念上声明了一个不受约束的模板。由于它位于另一个类中,因此在许多情况下都不会查找它,只能使用 ADL 找到它。在实现自定义点时,我仍然会避免使用不受约束的模板。
    • @DietmarKühl,我当然明白你的意思,我根本没有争论。你的解决方案更好 - 这就是我赞成它的原因:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 2012-04-26
    • 2016-06-21
    • 1970-01-01
    • 2018-10-09
    相关资源
    最近更新 更多