嵌套派生模板的运算符重载

3

我遇到了关于派生类和嵌套类的运算符重载问题。我尝试了很多方法,但都失败了。有人能帮忙解决吗?以下是代码:

class A:

template <typename T>
class A {
  public:
    virtual ~A() = default;
};

template <typename T>
ostream& operator<<(ostream& out, const A<T>& a) {
  out << "in A\n";
  return out;
}

B类:

template <typename T>
class B : public A<T> {};

template <typename T>
ostream& operator<<(ostream& out, const B<T>& b) {
  out << "in B\n";
  return out;
}

并测试代码:

A<int> *pa = new B<int>();
B<int> *pb = dynamic_cast<B<int> *>(pa);
cout << *pa << typeid(*pa).name() << endl;
cout << *pb << typeid(*pb).name() << endl;

我从结果中得到了需要的内容:

在A中

1BIiE

在B中

1BIiE

然后我创建了一个嵌套类,该类也派生自类A:

class BB::B:

template <typename T>
class BB {
  public:
    class B : public A<T> {};
};

template <typename T>
ostream& operator<<(ostream& out, const typename BB<T>::B& b) {
  out << "in BB::B\n";
  return out;
}

但是,当我用代码测试这个类时:

A<int> *pa2 = new BB<int>::B();
BB<int>::B *pb2 = dynamic_cast<BB<int>::B *>(pa2);
cout << *pa2 << typeid(*pa2).name() << endl;
cout << *pb2 << typeid(*pb2).name() << endl;

我只得到了一个意外的结果:

在A中

N2BBIiE1BE

在A中

N2BBIiE1BE

看起来编译器没有为BB::B特化重载运算符<<。这里有什么问题?

1个回答

3
template <typename T>
ostream& operator<<(ostream& out, const typename BB<T>::B& b);

b的类型处于一个不可推导的上下文中,它永远不会从这个签名中推导出T

你可以通过显式传递T来调用它。或者你可以编写一个从BB<T>::BB的类型映射,并变得非常高级。但这并不值得。


简单的选择是使用Koenig运算符。

template <typename T>
class BB {
  public:
    class B : public A<T> {
      friend ostream& operator<<(ostream& out, const B& b){
        out << "in BB::B\n";
        return out;
      }
    };
};

这个Koenig操作符是一个非模板函数,为BB<T>::B的每个实例化生成,并且只能通过ADL找到。


似乎未推断的上下文是最终答案。顺便问一下,如何“通过显式传递t来调用它”? - danceyat
1
该运算符应该是友元。 - David G
@dancy operator<< <T> 或类似的东西。 - Yakk - Adam Nevraumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接