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

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

например

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 класс является тривиальным типом (или даже может быть тривиально копируемым типом) в c ++ 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 работает с равномерной инициализацией, но не с конструктором копирования / перемещения. Но это может быть связано с тем, что массив является агрегатом, который не имеет конструктора или назначения копирования / перемещения. Хотя я не знаю, почему в c ++ 11 этот синтаксис не разрешен (особенно, когда они являются членами класса, неявное копирование / перемещение делает именно это).

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

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

5

Решение

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

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

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

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

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

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]