Почему некоторые типы не работают с единым синтаксисом инициализации?

Обновляя часть своего кода C++98 до C++11, я заметил, что юниформ-инициализация не такая унифицированная. Некоторые из них связаны с неполным типом, например void, а другие связаны с pod. например Для тривиально копируемых типов юниформ-инициализация не работает как для прямой инициализации, так и для инициализации копированием, когда инициализация включает конструктор копирования/перемещения.

e.g.

template<class T>
T foo() { return T("Hello World");}
foo<void>();
foo<std::string>();
--------
template<class T>
T foo() { return T{"Hello World"};}
foo<void>();
foo<std::string>();

В то время как первая часть компилируется, вторая половина дает сбой с error: compound literal of non-object type 'void'

struct pod { int x;int y;};
pod p{1,2}; //ok pod p(1,2) is error as usual
pod p2(p);

struct foo
{
    foo(foo const& rhs) : p_(rhs.p_){}
    pod p_;
};
--------
struct pod { int x;int y;};
pod p{1,2}; 
pod p2{p};

struct foo
{
    foo(foo const& rhs) : p_{rhs.p_}{}
    pod p_;
};

Здесь также вторая половина не работает при копировании с error: cannot convert 'pod' to 'int' in initialization. Хотя я думаю, что этот класс pod является тривиальным типом (или даже может быть тривиально копируемым типом) в С++ 11, но проблема остается той же за исключением примитивных типов

ПРИМЕЧАНИЕ:

в то время как следующие работы,

struct conv
{
    operator int()const { return 1;}
};
pod p{1,2};
pod p2{conv{}};

Это не так,

struct conv
{
    operator pod()const { return pod{1,2};}
};
pod p{1,2};
pod p2{conv{}};

Я также заметил, что массив C работает с юниформ-инициализацией, но не с конструктором копирования/перемещения. Но это может быть связано с тем, что массив является агрегатом, который не имеет конструктора копирования/перемещения или назначения. Хотя я не знаю, почему в С++ 11 этот синтаксис не разрешен (в частности, когда они являются членами класса, неявное копирование/перемещение делает именно это).

Итак, почему я не могу вслепую изменить всю инициализацию С++ 98 на равномерную инициализацию в стиле С++ 11 (ну, кроме типов, у которых есть список инициализаторов!)?

Я использую GCC 4.8.1.


person abir    schedule 03.10.2013    source источник
comment
Я заметил, что унифицированная инициализация не такая однородная. Вы правы, и я не могу не согласиться.   -  person Cassio Neri    schedule 03.10.2013


Ответы (1)


«Унифицированная инициализация» — нестандартный термин, который, к сожалению, использовался при продвижении функции списка инициализаторов на этапе ее предложения.

Нет, вы не можете использовать его везде. По моему опыту, лучше ограничиться

  • агрегаты (без конструктора; C++98 уже допускал это, но C++11 расширяет поддержку)
  • последовательности (initializer_list)
  • return по выражениям значений, вызывающим неявный конструктор

Слепое изменение всего и ожидание семантических изменений — это просто argumentsum ad novitatem — делать что-то, потому что это новое и необычное, а не потому, что это уместно.

Что касается универсального программирования, то да, сложно правильно поддерживать ситуации, охватывающие вышеуказанные категории. Размещайте конкретные жалобы на доске объявлений по адресу http://isocpp.org, и, возможно, ребята, отвечающие за язык, будут работать усерднее. восстановить общий порядок, который "единая инициализация" должна была улучшить, а не усугубить :v) .

person Potatoswatter    schedule 03.10.2013