2013-12-13 2 views
7

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

Update Нереальная, но гораздо проще версия

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); 
} 

ответ

7

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

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

оператор возврата с рамно-инициализации-лист инициализирует объект или ссылка должен быть возвращен из функции путем копирования списка инициализации (8.5. 4) из указанного списка инициализаторов.

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

+0

@PatrickFromberg См. Редактирование. Плохие новости :( – Potatoswatter

+0

Какой позор! Сначала они говорят нам быть чистыми и использовать * явным *, где это имеет смысл. Затем они забивают пальцы, когда мы делаем 8- (. –

+0

@PatrickFromberg TBH Я не уверен, явный' имеет смысл, кроме случая C++ 03, или когда вызов с несколькими аргументами может быть неоднозначным с перегрузкой 'std :: initializer_list'. Но без аргументов конструктор по умолчанию имеет особенно высокий приоритет над' std: : initializer_list' в любом случае. Номинальный эффект «явного» заключается в том, чтобы заставить вас назвать класс, а не позволять ему быть неявным, поэтому в этом случае он выполнил свою работу: P. – Potatoswatter

Смежные вопросы