Clang vs G++ lvalue to rvalue conversion
Asked Answered
P

1

1

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.

Peluso answered 1/6, 2020 at 8:42 Comment(2)
"seems that the difference between Clang and G++ is internally" The linked Q&A seems to say that the difference is in the std::pair implementations, not compiler behavior. "the output is same as Clang" "what the real reason for these different outputs" Do you get the same output for GCC and Clang, or different ones? If it's the same, what exactly is the question?Suggestible
@HolyBlackCat, the other question I have mentioned using pairs, in this case they are gives different results. the difference when using pairs instead of these assignments.Peluso
V
1

I think not everything in your example does what you think it does. The static_cast in the returns is meaningless, the result of cast1 and cast2 will automatically be an rvalue since you return by value. Further, cast1 and cast2 are also internally identical since std::remove_reference_t<Foo> is just Foo. You would need remove_reference if you had some templating going on.

Furthermore, you are mixing assignments with constructions. In T1 = cast2(Foo()); the following happens:

  1. A unnamed temporary is constructed by Foo(). This outputs default
  2. This temporary is copied to the foo argument of cast2. This outputs const, since we try to construct a Foo object from a temporary, and only const Foo&, not Foo&, can bind to a temporary.
  3. The static_cast does pretty much nothing.
  4. foo is returned. By return value optimization, the constructor that should be called, is not called.
  5. We assign the returned value by using the default (and implicit) assignment operator T1.operator=(const Foo&). Nothing gets printed.

In Foo const foo = T1 you call a constructor. Since T1 is an lvalue, you will call the constructor Foo(Foo&) and non-const is printed.

Vociferation answered 1/6, 2020 at 9:13 Comment(8)
I have notice that but I try too keep it same as move. h as I am not understand why g++ produce different output in case of pairs directly.Peluso
The assignments I understand that everything is not responable because the copy constructor mistake and assignments too I just simulating what happened when using pairPeluso
I am sorry, but I do not understand what you mean. I am pretty sure that your code above has nothing to do with the differences in the two pair implementations. If you can point me to where you looked at the different pair codes, I can have a look and try to explain where they are different.Vociferation
forward function std_pair. h, the code on the other question (pair), the first pair line 342 std_pair.h then 74 move.h and the second 292 std_pair.h. the problem when I am trying to understand the previous state there's a different of using same approach on g++ so I think it's not related directly to std_pair. h if so I should be able to simulate the output.Peluso
You should be aware that std_pair.h is not always the same code. There are different implementations of the standard library and I think that clang and gcc use different versions by default. This also means that std_pair.h on my PC is not necessarily the same as std_pair.h on yours and it most certainly is different from the std_pair.h on the mac of the original question.Vociferation
Somehow understand that, but I have spent a while doing some research and what I have found clang older versions just missing certain features, but now I sure they are different, but dealing with references should be the same especially for this type of implementation. I am not sure what if the implemtion I have found of std_pair. h belongs to clang, but if you have a direct link to the implmention file of the std_pair. h, I going to be grateful.Peluso
libstdc++ (the default for gcc and for clang on linux) and libc++ (the default for clang on macOS)Vociferation
Addendum: libc++ has pair in utility while libstdc++ has it in stl_pair.hVociferation

© 2022 - 2024 — McMap. All rights reserved.