rom1v
rom1v

Reputation: 2969

Member templates and inheritance

Please consider the following program:

#include <iostream>

template <typename T>
struct A {
    virtual void f(const T &) {
        std::cout << "A::f(const T &)" << std::endl;
    }
};

template <typename T>
struct B : A<T> {
    template <typename U>
    void f(const U &) override {
        std::cout << "B::f(const U &)" << std::endl;
    }
};

int main() {
    B<int> *b = new B<int>;
    A<int> *a = b;
    a->f(42);
    b->f(42);
}

Compile and execute with:

g++ -std=c++11 test.cpp -o test &&
./test

The output is:

A::f(const T &)
B::f(const U &)

The output proves that B::f does not override A::f, even if the override keyword is accepted by g++ (I consider this is a bug).

Although, clang++ does not accept override here:

$ clang++ -std=c++11 test.cpp -o test && ./test
test.cpp:13:23: error: only virtual member functions can be marked 'override'
    void f(const U &) override {
                      ^~~~~~~~~
1 error generated.

If I add a member B::f that really overrides A::f, the output is:

B::f(const T &)
B::f(const T &)

But how to call template <typename U> B::f(const & U) from that overriden implementation:

#include <iostream>

template <typename T>
struct A {
    virtual void f(const T &) {
        std::cout << "A::f(const T &)" << std::endl;
    }
};

template <typename T>
struct B : A<T> {
    void f(const T &) override {
        std::cout << "B::f(const T &)" << std::endl;
        // how to call template <typename U> f(const U &) from here?
    }

    template <typename U>
    void f(const U &) {
        std::cout << "B::f(const U &)" << std::endl;
    }
};

int main() {
    B<int> *b = new B<int>;
    A<int> *a = b;
    a->f(42);
    b->f(42);
}

Thank you

Upvotes: 1

Views: 40

Answers (1)

Wintermute
Wintermute

Reputation: 44023

You can call the member function template (or rather: the member function made from it) explicitly like this:

void f(const T &x) override {
    f<T>(x);
}

Upvotes: 2

Related Questions