The question related to this one. By tracing slt_pair. h and move. h, it's seems that the difference between Clang and G++ is internally. I have tried to simulate the assignment of the object (pair.first) as same as the implementation of std_pair.h, the output is same as Clang output it's reasonable output, but why when using pairs it's changes.
#include <iostream>
struct Foo {
Foo() {
std::cout << "default" << std::endl;
}
Foo(Foo& f2) {
std::cout << "non-const" << std::endl;
}
Foo(const Foo& f2) {
std::cout << "const" << std::endl;
}
};
// static_cast Foo lvalue to rvalue
Foo cast1(Foo foo){
return static_cast<Foo&&>(foo);
}
// same : check weather foo and Foo are the same type
Foo cast2(Foo foo){
return static_cast<typename std::remove_reference<Foo>::type&&>(foo);
}
int main() {
Foo T1; // pair Foo object
std::cout<<"Start"<<std::endl;
std::cout<<std::endl;
// (&&) rvalue casting
T1 = cast2(Foo()); // First pair object
std::cout << std::endl;
Foo const foo = T1;// Second pair object
}
How Clang deals with conversion lvalue to rvalue and what the real reason for these different outputs.
Any opinion is highly appreciated, Thanks.
Update: I have got a satisfying answers on the comments section of the accepted one.
I think not everything in your example does what you think it does. The
static_castin the returns is meaningless, the result ofcast1andcast2will automatically be an rvalue since you return by value. Further,cast1andcast2are also internally identical sincestd::remove_reference_t<Foo>is justFoo. You would needremove_referenceif you had some templating going on.Furthermore, you are mixing assignments with constructions. In
T1 = cast2(Foo());the following happens:Foo(). This outputsdefaultfooargument ofcast2. This outputsconst, since we try to construct aFooobject from a temporary, and onlyconst Foo&, notFoo&, can bind to a temporary.static_castdoes pretty much nothing.foois returned. By return value optimization, the constructor that should be called, is not called.T1.operator=(const Foo&). Nothing gets printed.In
Foo const foo = T1you call a constructor. SinceT1is an lvalue, you will call the constructorFoo(Foo&)andnon-constis printed.