The following code compiles cleanly, using g++ 6.3.0 with -Wall.
#include <iostream>
class Base
{
public:
Base(char const* base) : base_(base) {}
void print( char const* msg ) { print( base_, msg ); }
protected:
~Base() = default;
private:
char const* base_;
virtual void print( char const*, char const* ) = 0;
};
class Drv1 : public Base
{
public:
Drv1(char const* base, int i) : Base(base) , i_(i) {}
~Drv1() { std::cout << "Drv1 dtor" << std::endl; }
private:
int i_;
void print( char const* base, char const* msg ) override
{
std::cout << base << "(" << msg << "): " << i_ << std::endl;
}
};
class Drv2 : public Base
{
public:
Drv2(char const* base, double d) : Base(base) , d_(d) {}
~Drv2() { std::cout << "Drv2 dtor" << std::endl; }
private:
double d_;
void print( char const* base, char const* msg ) override
{
std::cout << base << "(" << msg << "): " << d_ << std::endl;
}
};
void do_test( char const* base, char const* msg, bool int_type )
{
Base&& _base(int_type ? (Base&&)Drv1(base, 1) : (Base&&)Drv2(base, 2.5));
_base.print( msg );
}
int main()
{
do_test( "Test1", "int", true );
do_test( "Test2", "double", false );
return 0;
}
The output, when run, is this:
Drv1 dtor
Test1(int): 1
Drv2 dtor
Test2(double): 2.5
Questions:
How can this be defined behavior if the derived class destructors have been invoked before the calls to the virtual functions? If the output is actually just a lucky accident, what are the compiler options to catch this issue?
Is
rvalue reference
the correct terminology for the type of the local variable_base
indo_test()
? Universal (or forwarding) references occur in the context of templates, but there are no templates here.