15

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.

phimuemue
  • 34,669
  • 9
  • 84
  • 115
  • What compiler are you using? I cannot get a warning in gcc or MSVS but I do in clang. – NathanOliver Oct 04 '16 at 12:07
  • Yes you're hiding it. Then what's your question? How to eliminate the verbose warning? – songyuanyao Oct 04 '16 at 12:10
  • @NathanOliver I used clang, but using g++ with warnings shows different behaviour. – phimuemue Oct 04 '16 at 12:12
  • @songyuanyao 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++. – phimuemue Oct 04 '16 at 12:13
  • 1
    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. – Sam Varshavchik Oct 04 '16 at 12:15
  • @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. – NathanOliver Oct 04 '16 at 12:19
  • @songyuanyao 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. – phimuemue Oct 04 '16 at 12:40
  • @phimuemue 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. – songyuanyao Oct 04 '16 at 12:50
  • @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. – AndyG Oct 04 '16 at 12:54
  • If you don't want the warning - either #pragma it away, or don't hide it. – UKMonkey Oct 04 '16 at 13:08

1 Answers1

5

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 {}
};
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • 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. – phimuemue Oct 04 '16 at 14:52
  • @phimuemue 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++. – Maxim Egorushkin Oct 04 '16 at 14:54