DEKKER
DEKKER

Reputation: 921

Assignement and addition overload for template objects

I am trying to learn templates and overloads at the same time. I have wrote the code below but I fail to do assignement of the data object with built-in types. What am I dooing wrong and how to solve it and yet better what is the best practice that can result in no intemediate-copy constructors to be called?

I want to have all the possible arithmetic operations. I think if I get it right for one of them (e.g. +) then others would be the same principles.

Do I need Copy/Move constructor and assignements?

#include <iostream>
#include <concepts>

template<typename T>
requires std::is_arithmetic_v<T>
class Data {
    private :
    T d;
    
    public: 
    Data(const T& data) : d{data}{
        std::cout << "Constructed Data with: " << d << std::endl;
    }
    Data(const Data& other) = default;
    ~Data() {
        std::cout << "Destructed: " << d << std::endl;
    }

    void operator+(const T& other) {
        this->d += other;
    }

    Data operator+(const Data& other) {
        return (this->d + other.d);
    }

    Data operator=(const Data& other) {
        return(Data(d + other.d));
    }

    void operator=(const T& t) {
        this->d += t;
    }

    Data operator=(const T& t) { // FAIL
        return Data(this->d + t);
    }
};

int main() {

Data a = 1;
Data b = 2;

Data c = a + b;
Data d = 10;
d = c + 1; // how to do this? FAIL

}

Compile Explorer Link

Upvotes: 1

Views: 50

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 311058

For starters you may not overload an operator just by the return type as

void operator=(const T& t) {
    this->d += t;
}

Data operator=(const T& t) { // FAIL
    return Data(this->d + t);
}

As for other problem then in this statement

d = c + 1;

the expression c + 1 has the return type void due to the declaration of the operator

void operator+(const T& other) {
    this->d += other;
}

The operator should be declared and defined like

Data operator +(const T& other) const
{
    return this->d + other;
}

The operators can be overloaded as it is shown below

template<typename T>
requires std::is_arithmetic_v<T>
class Data {
private:
    T d;

public:
    Data( const T &data ) : d{ data } {
        std::cout << "Constructed Data with: " << d << std::endl;
    }
    Data( const Data &other ) = default;
    ~Data() {
        std::cout << "Destructed: " << d << std::endl;
    }

    Data operator +( const T &other ) const {
        return this->d + other;
    }

    Data operator +( const Data &other ) const {
        return this->d + other.d;
    }

    Data & operator =( const Data &other ) {
        this->d = other.d;
        return *this;
    }

    Data & operator=( const T &t ) {
        this->d = t;
        return *this;
    }
};

Upvotes: 1

Deev
Deev

Reputation: 481

The problem is that you have defined both void operator=(const T& t) and Data operator=(const T& t). C++ does not allow two functions to differ by just the return type since it is impossible to resolve which overload should be called when.

Upvotes: 1

Related Questions