7
struct level0
{
  virtual void foo() = 0;
};

struct level1 : level0
{
  virtual void foo() { cout <<" level1  " << endl; }
};

struct level2 : level1
{
  virtual void foo() { cout <<" level2 " << endl; }
};

struct level3 : level2
{
  using level1::foo;
};

int main()
{
  level1* l1 = new level3;
  l1->foo();
  level3 l3;
  l3.foo();
  return 0;
}

the above code using gcc gives

level2
level1

but in icc gives

 level2
 level2

Which one is correct or is it undefined by standard?

Edit: This proves there is a bug for sure, consider the following main function

int main()
{
    level3 l3;
    l3.foo();               // This prints level1

    level3* pl3 = &l3;
    pl3->foo();             // This prints level2

    level3& rl3 = l3;
    rl3.foo();              // This prints level1

    level3& rpl3 = *pl3;
    rpl3.foo();             // This prints level2

    return 0;
}

So the same object when used directly produces different results and when used via a pointer of same type produces different results!!!

balki
  • 26,394
  • 30
  • 105
  • 151

3 Answers3

5

An example in Standard section 10.3p2 makes it clear that using declarations do not override virtual functions.

This is a known g++ bug.

As you noticed, when calling the member function via a reference or pointer, rather than a case in which the dynamic type is known, the bug does not happen.

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • 1
    +1 for standard quote, as for the bug: reported in 2004, last update in 2006 --> I guess nobody really cares given the easy work around :) – Matthieu M. Jan 12 '11 at 14:25
1

using level1::foo; introduces a foo function in level3 class which refers to level1::foo.

In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined. Such a using-declaration introduces the set of declarations found by member name lookup.

However, since level1::foo is virtual, I guess that by calling it you should call level2::foo, thus icc should be right.

I'm not so sure, anyway.

peoro
  • 25,562
  • 20
  • 98
  • 150
0

The way to get level1 level1 of course would be:

struct level3 : level2
{
   virtual void foo() { level1::foo(); }
};

Your "using" directive seems to be informing the compiler that if you have a level3 and call foo on it, it should invoke the level1 version, but it is not overwriting this to the v-table.

gcc looks wrong because of the inconsistency, not sure about icc because I don't know what the standard indicates.

CashCow
  • 30,981
  • 5
  • 61
  • 92