Reputation: 83
I'm looking to call a method of a base class A from a child class D that inherits it through C::A and B::A.
template <class PType>
class A
{
public:
template <class ChildClass>
void Func( void )
{
std::cout << "Called A<PType>::Func<ChildClass>" << std::endl;
}
};
template <class PType>
class B : public A<PType>
{
};
template <class PType>
class C : public A<PType>
{
};
class D : public B<int>, public C<int>
{
public:
D()
{
static_cast<B<int>*>( this )->A<int>::Func<D>();
static_cast<C<int>*>( this )->A<int>::Func<D>();
}
};
This works as expected, D calls both B::A::Func and C::A::Func with a template argument of the child class when initialized. This doesn't seem to work when D is a template class, however.
template <class PType>
class D2 : public B<PType>, public C<PType>
{
public:
D2()
{
//expected primary-expression before ‘>’ token
//expected primary-expression before ‘)’ token
static_cast<B<PType>*>( this )->A<PType>::Func< D2<PType> >();
static_cast<C<PType>*>( this )->A<PType>::Func< D2<PType> >();
}
};
The problem seems to be the template argument D2 to Func, but can't figure it out beyond that.
Upvotes: 4
Views: 215
Reputation: 275585
When you are working with a name whose value/type/template
status is dependent on a template
type parameter, you must disambiguate which one it is for the compiler manually.
This is to make the parsing far easier, and able to be done long before you pass a type into the template
.
You may think that is obviously a template
function call, but the <
and >
could be comparisons, and the template functions could be values or types or whatever.
By default, such dependent names are assumed to be values. If you want them to treat one as a type, use typename
. If you want to treat one as a template, use template
as a keyword.
So something like this:
static_cast<B<PType>*>( this )->template A<PType>::template Func< D2<PType> >();
now, when you are interacting with a fully instantiated template
this is not required. So:
static_cast<B<int>*>( this )->A<int>::Func< D2<PType> >();
consists of a fully instantiated template
type B<int>
, so A
's category is no longer dependent on a (locally undetermined) template
argument. Similarly, ->A<int>
is a fully instantiated template
type, so ::Func
is no longer dependent on a (locally undetermined) template
argument.
Upvotes: 1