0

Introduction

By using inheritance I can use base class methods from the derived class:

#include <sstream>
#include <functional>
#include <iostream>
#include <cmath>

template<typename TSelf, typename T, typename ...TBase>
requires requires { std::integral<T>; }
class Base
{
protected:
    T _multiplier;    
public:
    Base(T multiplier) : _multiplier{multiplier} {}

    T sum(T a, T b)
    {
        return (a + b) * _multiplier;
    }
};

template<typename T, typename ...TBase>
class Derived : public Base<Derived<T, TBase...>, T, TBase...> { };
    
int main() {
    Derived<int> derived { 10 };
    std::cout << derived.sum(5,5) << std::endl;
}

Problem:

There I am trying to add the method sum to the Derived class with another signature that differs from the Base's sum method signature:

#include <sstream>
#include <functional>
#include <iostream>
#include <cmath>

template<typename TSelf, typename T, typename ...TBase>
requires requires { std::integral<T>; }
class Base
{
protected:
    T _multiplier;    
public:
    Base(T multiplier) : _multiplier{multiplier} {}

    T sum(T a, T b)
    {
        return (a + b) * _multiplier;
    }
};

template<typename T, typename ...TBase>
class Derived : public Base<Derived<T, TBase...>, T, TBase...> 
{ 
public:
    T sum(T a, T b, T c)
    {
        return (a + b + c) * this->_multiplier;
    }
};
    
int main() {
    Derived<int> derived { 10 };
    std::cout << derived.sum(5,5) << std::endl;
}

And I have got this error:

<source>: In function 'int main()':
<source>:33:29: error: no matching function for call to 'Derived<int>::sum(int, int)'
   33 |     std::cout << derived.sum(5,5) << std::endl;
      |                  ~~~~~~~~~~~^~~~~
<source>:25:7: note: candidate: 'T Derived<T, TBase>::sum(T, T, T) [with T = int; TBase = {}]'
   25 |     T sum(T a, T b, T c)
      |       ^~~
<source>:25:7: note:   candidate expects 3 arguments, 2 provided

Workarounds:

  1. Use using base::methodName:
#include <sstream>
#include <functional>
#include <iostream>
#include <cmath>

template<typename TSelf, typename T, typename ...TBase>
requires requires { std::integral<T>; }
class Base
{
protected:
    T _multiplier;    
public:
    Base(T multiplier) : _multiplier{multiplier} {}

    T sum(T a, T b)
    {
        return (a + b) * _multiplier;
    }
};

template<typename T, typename ...TBase>
class Derived : public Base<Derived<T, TBase...>, T, TBase...> 
{ 
public:
    using base = Base<Derived<T, TBase...>, T, TBase...>;
    using base::sum;

    T sum(T a, T b, T c)
    {
        return (a + b + c) * this->_multiplier;
    }
};
    
int main() {
    Derived<int> derived { 10 };
    std::cout << derived.sum(5,5) << std::endl;
}
  1. Add the same overload in the derived class and call base class method from there by using base::methodName(args):
#include <sstream>
#include <functional>
#include <iostream>
#include <cmath>

template<typename TSelf, typename T, typename ...TBase>
requires requires { std::integral<T>; }
class Base
{
protected:
    T _multiplier;    
public:
    Base(T multiplier) : _multiplier{multiplier} {}

    T sum(T a, T b)
    {
        return (a + b) * _multiplier;
    }
};

template<typename T, typename ...TBase>
class Derived : public Base<Derived<T, TBase...>, T, TBase...> 
{ 
public:
    using base = Base<Derived<T, TBase...>, T, TBase...>;
    T sum(T a, T b)
    {
        return base::sum(a, b);
    }

    T sum(T a, T b, T c)
    {
        return (a + b + c) * this->_multiplier;
    }
};
    
int main() {
    Derived<int> derived { 10 };
    std::cout << derived.sum(5,5) << std::endl;
}

Questions

Question 1: Why does the derived class method shadows the base class method if their signatures are different?
Question 2: Are there other workarounds? I do not like the workarounds above because I have a lot of methods in my base class.

FreePhoenix
  • 127
  • 2
  • 8
  • That's just how c++ works. I don't think there are other workarounds – Alan Birtles Feb 26 '22 at 08:05
  • It's not about signatures at all, but about **names**. An `int sum;` would also hide `sum` from the base class (and from any other outer scope). – BoP Feb 26 '22 at 09:55

0 Answers0