Consider
struct Base
{
int foo(int);
int foo(int, int);
};
struct Child : Base
{
using Base::foo;
int foo(int, int, int);
};
Ideally I want to bring the Base
class foo
that takes only one int
as a parameter into the Child
class, and not the one that takes 2 int
s. Is there a way I can do that? My writing using Base::foo;
brings in both foo
methods of Base
.
A using declaration will make all overloads available. You can't prevent that from happening. But you can delete
the overloads you don't want, after the fact:
struct Base
{
int foo(int);
int foo(int, int);
};
struct Child : Base
{
using Base::foo;
int foo(int, int) = delete;
int foo(int, int, int);
};
Now using the two int overloads with a Child
is ill-formed. However that's not a perfect solution, since a client can still call the Base version:
Child c;
c.Base::foo(0, 0);
It's not possible to bring the specified overloaded function into the derived class. The rule of name lookup deals with names, but the overloaded functions have the same name foo
.
You can write a wrapper function at the derived class, e.g.
struct Child : Base
{
int foo(int x) { return Base::foo(x); }
int foo(int, int, int);
};
I'm going to list both solutions presented in other answers, and detail how they differ.
struct Child : Base
{
int foo(int x) { return Base::foo(x); }
int foo(int, int, int) { std::cout << 3; return 33; }
};
this does exactly what you want, but you have to repeat the signature.
A slightly different result is:
struct Child : Base
{
using Base::foo;
int foo(int,int)=delete;
int foo(int, int, int) { std::cout << 3; return 314; }
};
To see how this is different, imagine we did this:
struct Grandkid : Child
{
using Child::foo;
int foo(double, double) { std::cout << 2; return 42; }
};
and we did:
Grandkid x;
x.foo(3,4);
In the case with =delete
, this would generate a compiler error.
3,4
prefers int,int
over double,double
. When we =delete
the int,int
overload, it is still considered, selected, and we pick the =delete
d one. When we instead exclude it from overload resolution, 3,4
picks double,double
.
Manual forwarding excludes int,int
overload from being considered. =delete
does not.
This is most similar to the imaginary syntax of using Base::foo(int);
(ie, only bringing in one of the parent overloads of foo
).
Note that Grandkid
is just one simple way to detect the difference. The important thing is there is a difference between removing something from overload resolution, and =delete
ing the overload.
Live example where it works, and where it doesn't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With