Inspired by this question, I tried the following code:
struct A {
virtual void doit() const = 0;
};
struct B : public A {
virtual void doit() const;
};
struct C : public A {
virtual void doit() const;
};
void
foo(bool p)
{
const A &a = (p ? static_cast<const A &>(B()) : static_cast<const A &>(C()));
a.doit();
}
Every compiler I have tried accepts this code with -Wall -Werror
and generates the assembly I want. But after carefully reading the C++03 specification section 12.2 ("Temporaries") and section 5.12 ("Conditional Operator"), I am unsure whether this is guaranteed to work.
So, is this valid code, or does it invoke undefined behavior? Does the answer differ for C++03 and C++11?
Citations from relevant specifications would be appreciated.
Oh, it's very invalid.
Consider:
#include <iostream>
using namespace std;
struct A {
virtual ~A() { cout << "~A" << endl; }
virtual void doit() const = 0;
};
struct B : public A
{
~B() override { cout << "~B" << endl; }
void doit() const override { cout << "A::doit" << endl; }
};
struct C : public A
{
~C() override { cout << "~C" << endl; }
virtual void doit() const { cout << "C::doit" << endl; }
};
void foo(bool p)
{
cout << "foo( " << p << ")" << endl;
const A &a = (p ? static_cast<const A &>(B()) : static_cast<const A &>(C()));
a.doit();
}
auto main( int argc, char* argv[] ) -> int
{
cout << boolalpha;
foo( true );
cout << endl;
foo( false );
}
Output in Coliru Viewer, using g++ 4.8:
foo( true) ~B ~A pure virtual method called terminate called without an active exception bash: line 7: 16922 Aborted (core dumped) ./a.out
It's UB so any explanation could be true, but one can be reasonably sure, without looking at the assembly, that what happens is:
A
, which is abstract.A
is called.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With