ewr3243
ewr3243

Reputation: 441

error in child class definition of templated class inheritance

I am defining class A that can take function as template argument. Class B inherits class A. However, there are errors B: use of class template requires template argument list and multiple other errors. I am thinking that declaration of class B has gone wrong. However, I am not using any template for class B. Can someone comment?

#include <iostream>

void f_global()
{
    std::cout << "top level function\n";
}

template<typename F>
class A
{
public:
    F f1;
    A(F fun1) : f1(fun1) {}
    void fa();
};

template<typename F>
void A<F> :: fa()
{
    std::cout << "From A<F>::fa()\n";
    f1();
}

template<typename F>
class B : public A<F> //error
{
public:
    void fb();
};

void B::fb() //error
{
    std::cout << "From B::fb()\n";
    A::f1(); //Can access f1()?
}
int main()
{
    A obja(f_global); //error?
    obja.fa();
    B objb;
    objb.fb();
}

Upvotes: 1

Views: 78

Answers (1)

mfnx
mfnx

Reputation: 3018

First of all, it is often useful to explain what you are trying to achieve. There are many very smart people here which would come up with solutions to your problem which have absolutely nothing to do with yours.

Now, I've tried to guess what you wanted to achieve. Since you call fa from fb, I assumed B is a template. If not, then at least fb should be a templated function. However, since you don't pass the function to execute as argument to fb, I finally guessed that your class B is intented to be a template.

So, your global function is fine:

void f_global()
{
    std::cout << "top level function\n\n";
}

Your class A is ok, but for clearness, I'd use F for the function type and F* for the function pointer (*), and I would also store the function as a private member. However, to respect the code in your question, I'll leave it as a public member.

EDIT (*) As @Phil1970 pointed out, F is more general than F*as it would work with lambdas and std::function.

template <typename F>
class A
{
public:
    A(F fun) : _f {fun} {}
    void fa() { std::cout << "From A<F>::fa()\n"; _f(); }
    F _f;
};

As you correctly figured out, there is a problem with your class B. First of all, if template <typename F> B inherits from template <typename F> A, you should be able to construct an object of type A<F> from within the constructor of B<F>. In other words, B<F> should be able to construct A<F>, and therefore, you should pass the function f_global to the constructor of class B<F>.

template <typename F>
class B : public A<F>
{
public:
    B(F* fun) : A<F>(fun) {}
    void fb() { std::cout << "From B::fb()\n"; A<F>::_f(); }
    void fb1() { std::cout << "From B::fb1()\n"; this->template _f(); }
    using A<F>::_f;
    void fb2() { std::cout << "From B::fb2()\n"; _f(); }
};

I added functions fb1 and fb2 to show you how to call the callable _f member using template deduction and using the keyword using.

Upvotes: 2

Related Questions