I'm trying to detect, in the destructor , if I'm in a temporary instance or not.
The first thing I tried was to qualify the destroyers:
~S( ) & { ... }
~S( ) && { ... }
With which I got a nice error message:
error: destructors may not be ref-qualified
Next, I tried this:
#include <iostream>
#include <list>
using namespace std;
struct S {
S( ) { algo( ); }
S( const S& ) : S( ) { }
S( S && ) { algo( ); }
void realAlgo( bool tmp, bool dest ) const {
cout << ( tmp ? "Temporal " : "No temporal " );
cout << ( dest ? "destructor" : "constructor" ) << endl;
}
void algo( bool dest = false ) & {
realAlgo( false, dest );
}
void algo( bool dest = false ) && {
realAlgo( true, dest );
}
~S( ) { algo( true ); }
};
int main( void ) {
list< S > lista{ S( ), S( S( ) ) };
cout << "Size: " << lista.size( ) << endl;
return 0;
}
To my surprise, the output obtained is:
No temporary builder
Not temporary builder
Not temporary builder
Not temporary builder
Not temporary destroyer
Not temporary destroyer
Size: 2
Not temporary destroyer
No temporary destroyer
That is, is not called to member function algo( ) &&
.
After thinking about it a bit, it is a logical behavior, given that the decision to call one or another version of the function is done at compile time. Not being able to qualify the destructors, they will always call the version &
of the function.
So, I changed tactics. Why not use an indicator, and set it in the move constructor ?
#include <iostream>
#include <list>
using namespace std;
struct S {
bool temp;
S( ) : temp( false ) { cout << "Constructor\n"; }
S( const S& ) : S( ) { }
S( S &&o ) : S( ) { o.temp = true; }
~S( ) {
cout << "Destructor de " << ( temp ? "temporal" : "no temporal" ) << endl;
}
};
int main( void ) {
list< S > lista{ S( ), S( S( ) ) };
cout << "Size: " << lista.size( ) << endl;
return 0;
}
The result surprised me again:
Constructor
Builder
Builder
Builder
Destroyer of not temporary
Destroyer of not temporary
Size: 2
Destroyer of not temporary
Destroyer of non-temporal
So, the question is: