Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guaranteed copy elision and Nonmoveable{Nonmoveable{}}

I found GCC 7 has implemented guaranteed copy elision, and I tried the code below in wandbox:

#include <iostream>

struct NonMovable
{
    NonMovable() noexcept = default;
    NonMovable(NonMovable&&) noexcept = delete;
    NonMovable& operator=(NonMovable&&) noexcept = delete;
};

NonMovable Make()
{
    return {};
}


int main()
{
    //[[maybe_unused]] const auto x = Make();
    //const auto z = NonMovable{};
    [[maybe_unused]] const auto y = NonMovable{NonMovable{}};
}

And I got compile error:

prog.cc: In function 'int main()':
prog.cc:20:60: error: use of deleted function 'NonMovable::NonMovable(NonMovable&&)'
     [[maybe_unused]] const auto y = NonMovable{NonMovable{}};
                                                            ^
prog.cc:6:5: note: declared here
     NonMovable(NonMovable&&) noexcept = delete;
     ^~~~~~~~~~

According to cppreference:

In initialization, if the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object:
T x = T(T(T())); // only one call to default constructor of T, to initialize x

So I think it should be equal to const Movable y{};. What's wrong?

like image 984
Cu2S Avatar asked Oct 07 '16 15:10

Cu2S


1 Answers

List-initialization gives you no precise control over what happens. Basically the committee has guessed what the programmer might want to do most probably and assigned the corresponding meanings.

If you want to have precise control, use non-list initialization. For that, your testcase should work definitely.

If you stick to list-initialization, then for aggregates, I think current draft wording will do it and applies guaranteed copy "elision", because they say

If T is an aggregate class and the initializer list has a single element of type cv U, where U is T or a class derived from T, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).

In addition, you might get what you want in a future revision of the Standard or in a defect report resolution even for non-aggregates. I believe that your class is an aggregate, so it should compile. But perhaps there's something I'm missing here.

like image 150
Johannes Schaub - litb Avatar answered Oct 18 '22 06:10

Johannes Schaub - litb