Bug 66698 - Multiple inheritance from instantiations of template class and what about access to member functions
Summary: Multiple inheritance from instantiations of template class and what about acc...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.1.0
: P3 normal
Target Milestone: 7.0
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2015-06-29 20:11 UTC by Artur
Modified: 2021-08-04 21:36 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 7.1.0, 8.1.0
Known to fail: 6.1.0, 6.4.0
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Artur 2015-06-29 20:11:38 UTC
Let's take a look at the code:

template <typename C>
class S {
public:
    void add (C c) { ++cnt; }
    size_t size () const { return cnt; }

private:
    size_t cnt {}; 
};

struct Foo1 {};
struct Foo2 {};
struct Foo3 {};

class Z : public S<Foo1>, public S<Foo2>, public S<Foo3> {
public:
    using S<Foo1>::add;
    using S<Foo2>::add;
    using S<Foo3>::add;

    using S<Foo1>::size;    // (1)
    using S<Foo2>::size;    // (2)
    using S<Foo3>::size;    // (3)
};

And usage looks like this:

Z z;

z.add (Foo1 {});
z.add (Foo1 {});
z.add (Foo2 {});

cout << z.size () << endl;

This code compiles fine with gcc-5.1 (c++11), but this code does not compile under clang-3.5 (c++11 - sorry, I do not have newer version of clang).

Clang produces "error: call to member function 'size' is ambiguous" which is basically (from my point of view) correct, but gcc compiles it and returns 2.

Ok, but here is much more fun, if I switch the order of lines marked with comments (1) and (2), to get something like this:

using S<Foo2>::size;    // (2)
using S<Foo1>::size;    // (1)

The code still compiles on gcc and the result is: 1.

As you can imagine, if you write line (3) before these two, you will get 0.

So, from what I see, gcc gets first using declaration of S<C>::size, ignores rest of them and uses this one.

Is it a bug?

This question (bug) can be seen at http://stackoverflow.com/questions/31104690/multiple-inheritance-from-instantiations-of-template-class-and-what-about-access but I didn't receive reasonable answer there.

Best,

Artur
Comment 1 Andrew Pinski 2021-08-04 21:35:58 UTC
More self contained testcase (rather than the code snipit in comment #0):
#include <stddef.h>
#include <iostream>
template <typename C>
class S {
public:
    void add (C c) { ++cnt; }
    size_t size () const { return cnt; }

private:
    size_t cnt {}; 
};

struct Foo1 {};
struct Foo2 {};
struct Foo3 {};

class Z : public S<Foo1>, public S<Foo2>, public S<Foo3> {
public:
    using S<Foo1>::add;
    using S<Foo2>::add;
    using S<Foo3>::add;

    using S<Foo1>::size;    // (1)
    using S<Foo2>::size;    // (2)
    using S<Foo3>::size;    // (3)
};

int main(void)
{
    
Z z;

z.add (Foo1 {});
z.add (Foo1 {});
z.add (Foo2 {});

std::cout << z.size () << std::endl;
}
Comment 2 Andrew Pinski 2021-08-04 21:36:18 UTC
Also fixed in GCC 7+.