Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

operator overloading for nested derived templates

Tags:

c++

I've got some problem with operator overloading for derived and nested class. I've tried many ways but failed many times. Can anyone help to solve this? Here's the code:

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

class 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;
}

And test code:

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;

And I got what I need from result:

in A

1BIiE

in B

1BIiE

Then I created a nested class which is also derived from class 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;
}

But when I test this class with code:

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;

I got only an unexpected result:

in A

N2BBIiE1BE

in A

N2BBIiE1BE

Seems that compiler didn't specialize overloaded operator<< for BB::B. What's the problem here?

like image 954
danceyat Avatar asked Dec 21 '25 08:12

danceyat


1 Answers

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

The type of b is in a non-deduced context. It will never deduce T from this signature.

You can call it buy passing T explicitly. Or you could write a type map from BB<T>::B to B and get real fancy. But that isn't really worth it.


The easy option is a Koenig operator.

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

this Koenig operator is a non-template function that is generated for each instantiation of BB<T>::B, and can be found only via ADL.

like image 71
Yakk - Adam Nevraumont Avatar answered Dec 23 '25 22:12

Yakk - Adam Nevraumont



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!