Это не инициализация копирования, или это так?

В следующем коде мне не разрешено объявлять явный ctor, потому что компилятор говорит, что я использую его в контексте инициализации копирования (clang 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); 
}

1 ответ

Решение

= нотация не должна влиять на жалобу, поскольку привязка ссылки не ведет себя по-разному, независимо от того, выражена ли она прямой или инициализацией копирования. Здесь инициализируется объект возвращаемого значения, который не имеет собственного имени.

К сожалению, GCC имеет право жаловаться, как и Clang. Согласно §6.6.3/2 [stmt.return],

Оператор return со списком фигурных скобок инициализирует объект или ссылку, которые будут возвращены из функции путем копирования-инициализации списка (8.5.4) из указанного списка инициализатора.

Итак, есть невидимое = войдите туда, и вы не сможете обойти это.

Другие вопросы по тегам