dimanche 28 juin 2015

Multiple inheritance from instantiations of template class and what about access to member functions

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.

Could anybody tell me which compiler is doing correct work according to the C++ standard?

Best, Artur

Aucun commentaire:

Enregistrer un commentaire