0

I'm trying to overload a parent class's variadic template member function in the child class but I'm having some problems getting this to work.

Consider the following code:

#include <iostream>
#include <string>

class base {
public:
   base() {}
   template<typename... Args>
      void test(Args... args) {
         std::cout<<__PRETTY_FUNCTION__<<std::endl;
      }
};

class child : public base {
public:
   child() {}
   template<typename... Args>
      void test(Args... args) {
         std::cout<<__PRETTY_FUNCTION__<<std::endl;
      }
};


int main(int, char**)
{
   base* b = new base;
   base* c = new child;

   b->test(1);
   c->test(1);
   b->test(1, 1.2, "test");
   c->test(1, 1.2, "test");
   b->test("test", std::string("string"));
   c->test("test", std::string("string"));

   return 0;
}

When I run this I get the output

void base::test(Args ...) [with Args = {int}]
void base::test(Args ...) [with Args = {int}]
void base::test(Args ...) [with Args = {int, double, const char*}]
void base::test(Args ...) [with Args = {int, double, const char*}]
void base::test(Args ...) [with Args = {const char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]
void base::test(Args ...) [with Args = {const char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]

Only when I change base* c = new child; to child* c = new child; do I get the output that I want/expect:

void base::test(Args ...) [with Args = {int}]
void child::test(Args ...) [with Args = {int}]
void base::test(Args ...) [with Args = {int, double, const char*}]
void child::test(Args ...) [with Args = {int, double, const char*}]
void base::test(Args ...) [with Args = {const char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]
void child::test(Args ...) [with Args = {const char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]

What am I doing wrong here/do I not understand? I thought polymorphism would allow me to use the downcast pointer and still be able to access the functionality of the child class.

EDIT: Thank you all for your comments, seems that what I'm trying to do just isn't possible in c++. So I'll have to think of a different way to achieve what I want.

  • 4
    In order to call `child::test` through a `base*`, you need to make `test` virtual. However you cannot do this because `test` is templated and C++ doesn't allow virtual function templates. – paolo Jul 26 '22 at 19:27
  • This only works for `virtual` functions and you cannot make a function template `virtual`. – fabian Jul 26 '22 at 19:29

1 Answers1

0

You are attempting to utilize polymorphism where there isn't any. In order to make a class polymorphic (as in call the derived implementation of a function from a pointer/reference to the base class), the member function must be marked as virtual. This however cannot be done with function templates in C++. Sorry.

Your second example works, because it doesn't attempt any polymorphism, rather it knows at compile time the true type of the object.

DeiDei
  • 10,205
  • 6
  • 55
  • 80