5

When calling a non-templated member function in a base class one can import its name with using into the derived class and then use it. Is this also possible for template member functions in a base class?

Just with using it does not work (with g++-snapshot-20110219 -std=c++0x):

template <typename T>
struct A {
  template <typename T2> void f() {  }
};

template <typename T>
struct B : A<T> {
  using A<T>::f;

  template <typename T2> void g() {
    // g++ throws an error for the following line: expected primary expression before `>`
    f<T2>();
  }
};

int main() {
  B<float> b;
  b.g<int>();
}

I know that prefixing the base class explicitly as in

    A<T>::template f<T2>();

works fine, but the question is: is it possible without and with a simple using declaration (just as it does for the case where f is not a template function)?

In case this is not possible, does anyone know why?

Lars
  • 2,616
  • 3
  • 21
  • 18

2 Answers2

10

this works (pun intended): this->template f<T2>();

So does

template <typename T>
struct B : A<T> {
  template <typename T2> void f()
  { return A<T>::template f<T2>(); }

  template <typename T2> void g() {
    f<T2>();
  }
};

Why using doesn't work on template-dependent template functions is quite simple -- the grammar doesn't allow for the required keywords in that context.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Thanks, but both solutions do not really answer the question, as both are not simpler than saying `A::template f()` in the first place. – Lars Mar 09 '11 at 05:09
  • I think `this` is simpler, although that's a matter of taste of course. But it also allows virtual functions to be work as expected (although I see that is not an issue here). – dappawit Mar 09 '11 at 05:13
  • @Lars: `using` is not simpler than `A::template f()`... unless you are calling `f()` many times. In which case the wrapper function is also a simplification. – Ben Voigt Mar 09 '11 at 07:21
  • I disagree. Of course I have the case in mind where you have many calls to `f`, not just one. So repeating `A::template` or `this->template` all over the code is not very appealing. The wrapper solution is more complex than `using` because a) it is much longer, but more important b) you have to repeat the signature of `f`, so whenever you change `f` in the base class you have to do changes accordingly in the inheriting class (or: in *all* 10 inheriting classes...). I guess this is the reason why we have the `using` declaration at all. But why does it not work for templates? – Lars Mar 09 '11 at 09:24
1

I believe you should use:

this->A<T>::template f<T2>();

or:

this->B::template f<T2>();

eric zhu
  • 51
  • 6