I am trying to provide an API where an user can statically inherit from a base class and use its methods.
The issue is that the class is template
d with typename T
and the methods are template
d with typename U
, such that the use of the methods is really cumbersome (I think, for an API).
As far as I understood this is intended since the compiler cannot resolve (the dependent?) methods.
template<typename T>
struct base {
template<typename U>
void foo(){}
};
template<typename B>
struct child : B
{
void barr(){
B::template foo<float>();
this->template foo<float>();
/*
B::foo<float>(); - ERROR: expected primary-expression before ‘float’
this->foo<float>(); - ERROR: expected primary-expression before ‘float’
foo<float>(); - ERROR: error: ‘foo’ was not declared in this scope
*/
}
};
int main(){
child<base<bool>> c;
c.barr();
return 0;
}
Is there any way that I could get rid of template
keyword in the call to foo
?
Maybe some syntactic sugar I don't know of?
CodePudding user response:
You could add a foo
member function template to child
that just calls the one in B
. That is,
template<typename T>
struct base {
template<typename U>
void foo() {}
};
template<typename B>
struct child : B
{
void barr() {
foo<float>();
}
template<typename T>
void foo() {
typename B::template foo<T>();
}
};
CodePudding user response:
The problem is indeed caused by the compiler's need to resolve foo
before deciding that foo<
isn't calling operator<
on the expression foo
. Adding template
means that the compiler knows foo<
is the start of a template argument list.
As the author of base
, there's nothing you can do about that. That's the whole point of the two-phase compilation. The compiler trips over the foo<
in the first pass, where all it knows is that child<B>
inherits from some unknown B
.