operator<< C++ 模板 class 中成员类型的重载

operator<< overload for a member type in a template class in C++

在下面的代码中,我有一个模板 class,其中包含 成员类型 (结构元素)。我想为 成员类型 重载运算符 <<。但是,代码无法编译。

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

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!
}

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

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

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

例如,您可以使 elm 被推导为模板参数,例如

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

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

无法从嵌套实体中推导出模板参数(简短说明:不同模板实例化的类型可能相同)。即声明

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) { ... }
// ...

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