Home > Blockchain >  Bring to derived object the assignment operator from base (prior to C 11)
Bring to derived object the assignment operator from base (prior to C 11)

Time:06-23

I have a code similar to this:

template <typename T>
struct B
{
    B &operator =(const T &) { return *this; }
};

struct D : B<int> {};

int main()
{
    D d;
    d = 0;

    return 0;
}

Which fails:

error: no viable overloaded '='
   d = 0;
   ~ ^ ~
note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const D' for 1st argument
struct D : B<int> {};
       ^
note: candidate function (the implicit move assignment operator) not viable: no known conversion from 'int' to 'D' for 1st argument
struct D : B<int> {};
       ^

The error is easy to spot and understand: D lacks of assignment operator with int, even if its base class have it. From onwards we can solve this issue "lifting" to the derived object the assignment operator from the base object:

struct D : B<int> { using B::operator =; /* Easy fix! */ };

But I'm working on a project, so this fix isn't available. How was this solved prior to C 11?

CodePudding user response:

using declarations for inheriting base class methods already works in C 98.

It's using declarations to inherit constructors that doesn't.

template <typename T>
struct B {
    B(const T&) {}
    B &operator=(const T&) { return *this; }
};

struct D : B<int> {
    // using B<int>::B;           // error, constructors can't be inherited
    using B<int>::operator=;
};

and you then need to implement one that initializes the base class:

struct D : B<int> {
    D(int v) : B(v) {}          // this works
    using B<int>::operator=;    // and this too
};

CodePudding user response:

But I'm working on a c 98 project, so this fix isn't available. How was this solved prior to C 11?

Define an operator= in D that calls B::operator=:

struct D : B<int> {
    D& operator=(const int &rhs) {
        B<int>::operator=(rhs);
        return *this;
    }
};

CodePudding user response:

First things first, the program(with using declaration) works with C 98. Working Demo with C 98.

That is, a using declaration for the assignment operator of the base class inside the derived class is allowed by C 98. Here is the relevant text from the standard:

If an assignment operator brought from a base class into a derived class scope has the signature of a copy-assignment operator for the derived class (12.8), the using-declaration does not by itself suppress the implicit declaration of the derived class copy-assignment operator; the copy-assignment operator from the base class is hidden or overridden by the implicitly-declared copy- assignment operator of the derived class, as described below.

(emphasis mine)

Note again that the important thing is that the using declaration for the assignment operator of base class is allowed.

Now, you can define an assignment operator= for the derived class that explicitly uses the base class as shown below:

struct D : B<int> {
    D& operator=(const int& obj) {
        B<int>::operator=(obj); //use base class assignment operator
        return *this;
    }
    
};

CodePudding user response:

You can add the required operator function to your derived class and call the corresponding base class operator from that:

template <typename T>
struct B {
    B& operator = (const T&) { return *this; }
};

struct D : B<int> {
    D& operator = (const int& rhs) {
        B<int>::operator = (rhs);
        return *this;
    }
};

int main()
{
    D d;
    d = 0;

    return 0;
}
  • Related