В следующем коде мне не разрешено объявлять явный Ctor, потому что компилятор говорит, что я использую его в копия инициализация контекст (лязы 3.3 и gcc 4.8).
Я пытаюсь доказать неправоту компиляторов, сделав ctor неявным, а затем объявив конструкторы копирования удаленными.
Компиляторы не правы или есть другое объяснение?
#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;
}
Обновить Нереалистичная, но гораздо более простая версия
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);
}
=
нотация не должна влиять на жалобу, поскольку привязка ссылки не ведет себя по-разному, независимо от того, выражается ли она при прямой инициализации или инициализации копирования. Здесь инициализируется объект возвращаемого значения, который не имеет собственного имени.
К сожалению, GCC имеет право жаловаться, как и Clang. Согласно §6.6.3 / 2 [stmt.return],
Оператор return со списком фигурных скобок инициализирует объект или ссылку, которые должны быть возвращены из функции путем копирования-инициализации списка (8.5.4) из указанного списка инициализатора.
Итак, есть невидимое =
войдите туда, и вы не сможете обойти это.
Других решений пока нет …