Дочерний класс вызывает неожиданную перегруженную функцию - PullRequest
1 голос
/ 25 марта 2019

Я изо всех сил пытаюсь понять, почему в следующем коде вызывается предположительно неправильная перегрузка.

// overload.h
 struct T1
    {
      template<class... Args>
      void doFoo(Args&&... args)
        {
        std::cout << "T1 doFoo generic"<< std::endl;
        }

      void doFoo(int a)
        {
        std::cout << "T1 doFoo INT "<< std::endl;
        }

      void doFoo(double a)
        {
        std::cout << "T1 doFoo Double "<< std::endl;
        }

      template<class... Args>
      void foo(Args&&... args)
        {
        doFoo(args...);
        }
    };


  struct T2 : public T1
    {
      void doFoo(char c)
        {
        std::cout << "T2 doFoo char " << std::endl;
        }
    };

  // main.cpp

  #include <overload.h>
  int main()
    {
    T2 t2;
    t2.foo(3);
    t2.foo('A'); // This outputs: T1 doFoo generic 
    }

Я ожидал, что t2.foo ('A') будет иметь в качестве вывода: "T2 doFoochar ", но вместо этого я получил" T1 doFoo generic ".

Если я переместу T2 :: doFoo (char c) в T1, все будет работать как положено.В чем причина такого поведения?любой обходной путь?

1 Ответ

1 голос
/ 25 марта 2019

Как уже предлагалось в комментарии, поскольку T1 не знает о производной структуре T2, T1::foo также не может найти T2::doFoo(char c), и эта статическая привязка не может быть достигнута.

Простой обходной путь для внезапной перегрузки T1::foo для char в T2 будет снова объявить foo в T2 и перегрузить его следующим образом:

DEMO

struct T1 
{
    template<class... Args>
    void doFoo(Args&&... args){
        std::cout << "T1 doFoo generic"<< std::endl;
    }

    void doFoo(int a){
        std::cout << "T1 doFoo INT "<< std::endl;    
    }

    void doFoo(double a){
        std::cout << "T1 doFoo Double "<< std::endl;
    }

    template<class... Args>
    void foo(Args&&... args){
        doFoo(std::forward<Args>(args)...);
    }
};

struct T2 : public T1
{
    template<class... Args>
    void foo(Args&&... args){
        T1::foo(std::forward<Args>(args)...);
    }

    void foo(char c){
        std::cout << "T2 foo char " << std::endl;
    }
};
...