Template class inheritance
CDerived<int> di(dd1); // <- The problem is here
This invokes the first constructor of CDerived
, and so T2
is inferred as CDerived<double>
which is the type of dd1
. Then, dd1
becomes x
in the constructor; x
which is CDerived<double>
, gets passed to the base class constructor which accepts int
(which is the value of the type argument T
to CDerived
class template). Hence the error, as CDerived<double>
cannot be converted into int
. Note that T
of CBase
is int
.
See it as:
CDerived<int> di(dd1); // <- The problem is here
^ ^
| |
| this helps compiler to deduce T2 as double
|
this is T of the CDerived as well as of CBase
If you want to make your code work, then do this:
- First derive publicly instead of privately.
- Add another constructor taking
CDerived<T2>
as parameter.
So you need to so this:
template<class T> class CDerived : public CBase<T> //derived publicly
{
public:
template <class T2> CDerived(const T2 &x) : CBase<T>(x) {;}
//add this constructor
template <class T2> CDerived(const CDerived<T2> &x) : CBase<T>(x.var()) {;}
template <class T2> CDerived (const CBase<T2> &x) : CBase<T>(x) {;}
~CDerived() {;}
};
It should work now : online demo
Vincent
Researcher, astrophysicist, computer scientist, programming language expert, software architect and C++ standardization committee member. LinkedIn: https://www.linkedin.com/in/vincent-reverdy
Updated on July 09, 2022Comments
-
Vincent almost 2 years
I have a problem with the following piece of code (it is a very simplified example that reproduce the error in my program) :
#include <iostream> using namespace std; template<class T> class CBase { public: template <class T2> CBase(const T2 &x) : _var(x) {;} template <class T2> CBase (const CBase<T2> &x) {_var = x.var();} ~CBase() {;} T var() const {return _var;} protected: T _var; }; template<class T> class CDerived : public CBase<T> { public: template <class T2> CDerived(const T2 &x) : CBase<T>(x) {;} template <class T2> CDerived (const CBase<T2> &x) : CBase<T>(x) {;} ~CDerived() {;} }; int main() { CBase<double> bd(3); CBase<int> bi(bd); // <- No problem CDerived<double> dd1(3); CDerived<double> dd2(dd1); CDerived<int> di(dd1); // <- The problem is here return 0; }
And the error is the following :
error: cannot convert 'const CDerived<double>' to 'int' in initialization
How to solve that ? (with a preference for modifications in the base class and not in the derived class, and if possible no use of virtuality)
Thank you very much
EDIT : If I replace the concerned line with :
CDerived<int> di(CBase<int>(CBase<double>(dd1)));
it works but it is not very practical...EDIT : Seems to be solved by that :
template <class T2> CDerived(const CDerived<T2> &x) : CBase<T>(static_cast<const CBase<T2>&>(x)) {;}