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:
- 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;
}
- 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.