Home > OS >  C Overridden operator= to switch between Template types
C Overridden operator= to switch between Template types

Time:06-17

I have a template class that multiple classes are inheriting from to basically make some user friendly builders, hiding the functions that are not required on different builders, while following DRY

However I'm having trouble switching between the builder types. I'd prefer to use the operator= to switch without hassle and have the following code.

template<class T>
class BuilderFunctions
{
protected:
    std::string text;

public:
    template<class Other>
    BuilderFunctions<T>& operator=(const Other& other);
};

template <class T>
template <class Other>
BuilderFunctions<T>& BuilderFunctions<T>::operator=(const Other& other)
{
    //yes, I need same object protection
    text= other.text;
    return *this;
}

classes

class BuilderGenericList : public BuilderFunctions<BuilderGenericList>{
public:
    BuilderGenericList() = default;
};

//Build configuration details
class BuilderRootList : public BuilderFunctions<BuilderRootList>
{
private:
//I'll delete the functions I don't want accessed here

public:
    BuilderRootList() = default;
};

Code that says no

//Real world you'd build the root first and switch out to another builder or be using a prototype to seed another builder
BuilderRootList cmakeRoot;
BuilderGenericList list;
//Separate to make sure it's not trying to use cop constructor
list = cmakeRoot;

Accept I might be doing something I shouldn't be doing with template classes, although others seem to have success with templates the operators, so assume possible and I'm making some kind of mistake.

More info: The error I get is:

Severity Code Description Project File Line Suppression State Error C2679 binary '=': no operator found which takes a right-hand operand of type 'BuilderRootList' (or there is no acceptable conversion)

So It's definitely looking for my operator=, it's jsut not generating one from the template

CodePudding user response:

When you do the template inheritance, you have to be explicit in case of base classes members. More read:

In your case, the members text, and operator=, can be brought via using declaration.

class BuilderGenericList : public BuilderFunctions<BuilderGenericList> 
{
public:
    BuilderGenericList() = default;
    using BuilderFunctions<BuilderGenericList>::text;
    using BuilderFunctions<BuilderGenericList>::operator=;
    // ... so on, other members from base if needed!
};

// Build configuration details
class BuilderRootList : public BuilderFunctions<BuilderRootList>
{
public:
    BuilderRootList() = default;
    using BuilderFunctions<BuilderRootList>::text;
    using BuilderFunctions<BuilderRootList>::operator=;
    // ... so on, other members from base if needed!
};

Live Demo

Note that, this will make the memberusing BuilderFunctions<BuilderGenericList>::text public, if this is not what wanted, consider the suggestion by @Jarod42 in other answer.

CodePudding user response:

BuilderFunctions<T1> cannot access private/protected member of BuilderFunctions<T2> (with T1 != T2): add accessor, or make them friend.

in addition, you also have to put using for operator=:

template<class T>
class BuilderFunctions
{
    template <typename U> friend class BuilderFunctions;
protected:
    std::string text;

public:
    template<class Other>
    BuilderFunctions<T>& operator=(const Other& other);
};

template <class T>
template <class Other>
BuilderFunctions<T>& BuilderFunctions<T>::operator=(const Other& other)
{
    //yes, I need same object protection
    text= other.text;
    return *this;
}


class BuilderGenericList : public BuilderFunctions<int>{
public:
    using BuilderFunctions<int>::operator=;

    BuilderGenericList() = default;
};

//Build configuration details
class BuilderRootList : public BuilderFunctions<float>
{
private:
//I'll delete the functions I don't want accessed here

public:
    using BuilderFunctions<float>::operator=;

    BuilderRootList() = default;
};

Demo

  • Related