[Bug c++/84451] New: Multiple invocation of virtual base class constructor in diamond inheritance
tolez_xuninada at hotmail dot com
gcc-bugzilla@gcc.gnu.org
Mon Feb 19 06:51:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84451
Bug ID: 84451
Summary: Multiple invocation of virtual base class constructor
in diamond inheritance
Product: gcc
Version: 5.5.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: tolez_xuninada at hotmail dot com
Target Milestone: ---
I have a virtual and multiple inheritance situation: classes E<int> and
F<int> inherits virtually from Root<int> and G<int>
inherits from a wrapper class MultipleInherit<Root<int>,E<int>,F<int>>,
which in turns inherit from E<int> and F<int>. Here's a minimal working
example:
In testbases1.cpp:
#include<iostream>
#include<utility>
#include<type_traits>
using namespace std;
namespace details {
template
<
template <class,class> class BinaryPred,
class FirstOp,
class SecondOp,
class ... RestOp
> struct OneToAll {
static constexpr bool value =
BinaryPred<FirstOp,SecondOp>::value &&
OneToAll<BinaryPred,FirstOp,RestOp...>::value;
};
template
<
template <class,class> class BinaryPred,
class FirstOp,
class SecondOp,
class ... RestOp
>
constexpr bool OneToAll_v =
OneToAll<BinaryPred,FirstOp,SecondOp,RestOp...>::value;
template
<
template <class,class> class BinaryPred,
class FirstOp,
class SecondOp
>
struct OneToAll<BinaryPred,FirstOp,SecondOp> {
static constexpr bool value = BinaryPred<FirstOp,SecondOp>::value;
};
struct EmptyBase {};
template < class VirtualBase, class ... Bases >
struct MultipleInherit :
public
std::conditional_t<OneToAll_v<std::is_base_of,VirtualBase,Bases...>,
EmptyBase,
VirtualBase>,
public Bases...
{
static constexpr std::size_t NBases = sizeof...(Bases)+1;
template < class ... Args >
MultipleInherit(Args&&... args)
:VirtualBase(std::forward<Args>(args)...)
,Bases{std::forward<Args>(args)...}...
{
cout << "MI()\n";
}
};
}
using namespace details;
template <class T>
struct Root {
Root(T& i, const double& d) : ri_(i), d_(d) { cout << "Root()\n"; };
protected:
T& ri_;
double d_;
};
template < class T >
struct E : public virtual Root<T> {
E(T& i, const double& d) : Root<T>(i,d) {
cout << "E()\n";
}
};
template < class T >
struct F : public virtual Root<T> {
F(T& i, const double& d) : Root<T>(i,d) {
cout << "F()\n";
}
};
template < class T >
struct G : public MultipleInherit<Root<T>,E<T>,F<T>> {
using BaseType = MultipleInherit<Root<T>,E<T>,F<T>>;
G(T& i, const double& d) : Root<T>(i,d),BaseType(i,d) {
cout << "G()\n";
}
};
int main(int argc, char* argv[]) {
int i = 3;
double d = 4;
G<int> g(i,d);
}
If I compile with gcc 7.3.0: g++ testbases1.cpp -o testbases1 -g -std=c++14,
I get the expected output:
Root()
E()
F()
MI()
G()
I also tried clang++ which gives the correct answer too. But if I compile with
gcc 5.5.0, I get:
Root()
Root()
E()
Root()
F()
MI()
G()
The gcc 5.5.0 is obviously giving the wrong answer because one would expect
the virtual base is only constructed once in this situation.
More information about the Gcc-bugs
mailing list