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:
- Why do I have to access template base class members through the this pointer?
- Derived template-class access to base-class member-data
- Accessing base member functions in class derived from template class
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!
};
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;
};