In the following code I am not allowed to declare an explicit ctor because the compiler says I am using it in a copy-initializing context (clang 3.3 and gcc 4.8). I try to prove the compilers wrong by making the ctor non explicit and then declaring the copy constructors as deleted.
Are the compilers wrong or is there any other explanation?
#include <iostream>
template <typename T>
struct xyz
{
constexpr xyz (xyz const &) = delete;
constexpr xyz (xyz &&) = delete;
xyz & operator = (xyz const &) = delete;
xyz & operator = (xyz &&) = delete;
T i;
/*explicit*/ constexpr xyz (T i): i(i) { }
};
template <typename T>
xyz<T> make_xyz (T && i)
{
return {std::forward<T>(i)};
}
int main ()
{
//auto && x = make_xyz(7);
auto && x (make_xyz(7)); // compiler sees copy-initialization here too
std::cout << x.i << std::endl;
}
Update An unrealistic but much simpler version
struct xyz {
constexpr xyz (xyz const &) = delete;
constexpr xyz (xyz &&) = delete;
xyz & operator = (xyz const &) = delete;
xyz & operator = (xyz &&) = delete;
int i;
explicit constexpr xyz (int i): i(i) { }
};
xyz make_xyz (int && i) {
return {i};
}
int main () {
xyz && x = make_xyz(7);
}
The =
notation should not affect the complaint because reference binding doesn't behave differently whether expressed by direct- or copy-initialization. What's being initialized here is the return value object, which does not have its own name.
Unfortunately, GCC is right to complain, as does Clang. According to §6.6.3/2 [stmt.return],
A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization (8.5.4) from the specified initializer list.
So, there is an invisible =
sign there and you can't get around it.
来源:https://stackoverflow.com/questions/20559603/this-is-not-copy-initializing-or-is-it