I am trying to move from T t{ ... };
construction to auto t = T{ ... };
in order to make it consistent with function calls like auto p = std::make_unique<T>(...);
.
I am however running into issues when T
is not move-assignable:
struct nonmoveable {
nonmoveable(const nonmoveable&) = delete;
nonmoveable(nonmoveable&&) = delete;
nonmoveable& operator=(const nonmoveable&) = delete;
nonmoveable& operator=(nonmoveable&&) = delete;
};
int main() {
nonmoveable x = {};
auto y = nonmoveable{};
}
The code above compiles fine on GCC and clang, but fails on MSVC. Changing auto
to nonmoveable
results in the same error:
(10): error C2280: 'nonmoveable::nonmoveable(nonmoveable &&)': attempting to reference a deleted function (3): note: see declaration of 'nonmoveable::nonmoveable' (3): note: 'nonmoveable::nonmoveable(nonmoveable &&)': function was explicitly deleted
Who is correct according to the standard?
I know that recent revisions introduced a lot of rules regarding copy and move ellisions, but it is not clear to me whether you are allowed to ellide a deleted operation. Pure compiler optimization using the "as if" rule would clearly be forbidden, since the naively equivalent auto y = std::move(x);
cannot compile.
Answered in comments by @cpplearner:
Guaranteed copy/move ellision which allows the code to work even if the copy/move is explicitly or implicitly deleted was added in C++17
Issue is not about compilers, but by the their default C++ versions. MSVC -std:c++14
and GCC/clang -std=c++14
all fail to compile, while for c++17
they all work, as expected.