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.

Community
  • 1
  • 1
4.Pi.n
  • 1,151
  • 6
  • 15
  • *"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? – HolyBlackCat Jun 01 '20 at 09:10
  • @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. – 4.Pi.n Jun 01 '20 at 09:14

1 Answers1

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.

n314159
  • 4,990
  • 1
  • 5
  • 20
  • 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. – 4.Pi.n Jun 01 '20 at 09:18
  • The assignments I understand that everything is not responable because the copy constructor mistake and assignments too I just simulating what happened when using pair – 4.Pi.n Jun 01 '20 at 09:21
  • 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. – n314159 Jun 01 '20 at 09:25
  • 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. – 4.Pi.n Jun 01 '20 at 09:36
  • 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. – n314159 Jun 01 '20 at 09:46
  • 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. – 4.Pi.n Jun 01 '20 at 09:54
  • 1
    [libstdc++](https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3) (the default for gcc and for clang on linux) and [libc++](https://github.com/llvm-mirror/libcxx) (the default for clang on macOS) – n314159 Jun 01 '20 at 09:59
  • 1
    Addendum: libc++ has pair in [utility](https://github.com/llvm/llvm-project/blob/master/libcxx/include/utility) while libstdc++ has it in [stl_pair.h](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_pair.h) – n314159 Jun 01 '20 at 10:15