Hiding overloaded virtual function
Asked Answered
H

1

16

Consider the following hierarchy of structs:

struct I1 {
    virtual void doit() = 0;
};

struct I2 {
    virtual void doit(int) = 0;
};

struct I12 : I1, I2 {
    using I1::doit;
    using I2::doit;
};

struct Derived : I12 {
    void doit(int) override {}
};

Compiling this (using clang, or g++ with -Woverloaded-virtual) gives me a warning:

'Derived::doit' hides overloaded virtual function [-Woverloaded-virtual]

However, if I change I12 to the following, it compiles fine under clang, while g++ -Woverloaded-virtual still gives a warning:

struct I12 : I1, I2 {
    using I1::doit;
    void doit(int) override = 0;
};

Where is the difference between using I2::doit and void doit(int) override = 0? Naively, I would have thought that the former is sufficient to inform the compiler that I am aware that there are two versions of doit.

Hither answered 4/10, 2016 at 11:56 Comment(10)
What compiler are you using? I cannot get a warning in gcc or MSVS but I do in clang.Emoryemote
Yes you're hiding it. Then what's your question? How to eliminate the verbose warning?Should
@Emoryemote I used clang, but using g++ with warnings shows different behaviour.Hither
@Should True, I'm hiding it. But I do not really get why one version still issues a warning, while the other does not. Even more confusing to me is the differing behaviour of clang and c++.Hither
The C++ standard does not require compilers to issue warnings for any particular scenarios. Compilers are free to choose to warn about this, that, or the other. One compiler may choose to issue a warning in a particular situation where a second compiler will process without a warning. That doesn't make either compiler right or wrong.Peshitta
@SamVarshavchik The Standard mandates the compiler shall issue diagnostics in many cases. Whether that is a warning or an error is up to the compiler. I just do not know if this case is mandated or it is just something the compiler is doing as an added bonus.Emoryemote
@Should Basically, I am trying to get rid of the warnings in a clean way. I (think I) could add a using-declaration in Derived, but in my concrete case, I have Derived1, Derived2, ..., and possibly even doit1, doit2..., so I do not want to repeat all those using-declaratios everywhere, but if possible only at one central place.Hither
@Hither If you want to call doit() on Derived, you have to do it for every derived class. Otherwise, you might need some help from compiler options.Should
@NathanOliver: The closest I can find is 3.3.10 /4 [basic.scope.hiding] " During the lookup of a name qualified by a namespace name, declarations that would otherwise be made visible by a using-directive can be hidden by declarations with the same name in the namespace containing the using-directive;" But nowhere does it say a diagnostic is required.Aventine
If you don't want the warning - either #pragma it away, or don't hide it.Paramaribo
B
6

It complains that doit is hidden in Derived. A fix:

struct Derived : I12 {
    using I12::doit; // Bring all doit declarations from I12 into this scope.
    void doit(int) override {}
};
Botelho answered 4/10, 2016 at 14:47 Comment(2)
Thanks for your suggeestion, but in my concrete case, I have Derived1, Derived2, ..., and possibly even doit1, doit2..., so I do not really want to repeat all those using-declaratios everywhere, but if possible only at one central place.Hither
@Hither With such a design it may be easier to turn off the warning. -Wno-overloaded-virtual. Otherwise you will have to sprinkle using all over the place because this is how name hiding works in C++.Botelho

© 2022 - 2024 — McMap. All rights reserved.