Почему единый синтаксис инициализации применяется только для объектов?

В С++ 11 у нас есть хороший унифицированный синтаксис инициализации объектов. Почему он не распространяется и на инициализацию необъектных типов?

Есть ли в этом какая-то синтаксическая двусмысленность, или это просто какой-то глупый вопрос, который я задаю?

Пример:

struct s{ int k;};
s s1{1}; //ok (object initialization)
s const& s3{3};  //ok (object initialization)
s& s2{s1};  //error (reference initialization)

Более полезный пример:

struct t{ t(t const& x) : k(x.k){} int k;};
struct c
{
  c(t& x1,t& x2) 
    : s1_{x1} //error (reference initialization)
    , s2_{x2} //ok (object initialization)
   {}
 t& s1_;
 t s2_;
};

Еще один :

template<class T>
T get()
{
   return T{};
}

//ok (object initialization)
get<int>(); 
//error (void initialization? I do not know terminology for void() token equivalent)
get<void>();

person abir    schedule 11.06.2013    source источник
comment
Я предполагаю, что разработчики языка решили, что существующего синтаксиса s1_(x1) вполне достаточно.   -  person Sergey Kalinichenko    schedule 11.06.2013
comment
@dasblinkenlight это явно не так (считай MVP).   -  person R. Martinho Fernandes    schedule 11.06.2013
comment
Ваш последний пример незаконен. void — неполный тип объекта; нет возможности создавать объекты типа void.   -  person Angew is no longer proud of SO    schedule 11.06.2013
comment
@R.MartinhoFernandes Я согласен с тем, что синтаксис s1_(x1) и его последствия, безусловно, раздражают - они постоянно сбивают с толку новых практиков, способствуя восприятию C ++ как сложного языка. К сожалению, уже слишком поздно что-то менять в C++11: как только появится функция такого масштаба, она исчезнет навсегда.   -  person Sergey Kalinichenko    schedule 11.06.2013
comment
@Angew Я думаю, что void не является объектом, так как std::is_object<void>::value ложно. Так что нет возможности создать пустоту, так же как и нельзя create ссылаться. Однако C++ позволяет возвращать токен void() (и, к сожалению, не передавать в параметр!), который выглядит как конструктор, но не позволяет возвращать void{} как некоторый токен. И это то, что я спросил, какой синтаксис {} не для не-объектов   -  person abir    schedule 11.06.2013
comment
void — это неполный тип, и его невозможно заполнить.   -  person R. Martinho Fernandes    schedule 11.06.2013
comment
Относительно ссылок: константную ссылку можно инициализировать, используя унифицированный синтаксис инициализации в соответствии с 8.5.4/3, 5-й пункт. Он инициализируется путем создания временного файла, а затем продления его срока службы. Что касается неконстантных ссылок, в пункте, который следует за этим правилом, говорится, что ссылка может быть инициализирована из одноэлементного списка инициализаторов. Насколько я понимаю, это означает, что s& s2 { s1 }; действительно должно быть возможно.   -  person jogojapan    schedule 11.06.2013
comment
@jogojapan Для неконстантной ссылки gcc 4.8.1 говорит: invalid initialization of non-const reference of type 's&' from an rvalue of type '<brace-enclosed initializer list>'. не знаю насчет лязга   -  person abir    schedule 11.06.2013
comment
Да, GCC не работает. Это не приведет к сбою, если вы используете более простой тип (например, int вместо структуры). Тем не менее, в 8.5.4/3 сказано: [...] В противном случае, если список инициализаторов имеет один элемент, объект или ссылка инициализируется из этого элемента; [...] Следует признать, что предыдущее правило объясняет, что для всех ссылок создается временная ссылка, и если ссылка неконстантна, программа представляет собой некорректную попытку связать неконстантную ссылку lvalue к временному. Мне непонятно, почему они поставили правила в таком порядке.   -  person jogojapan    schedule 11.06.2013


Ответы (1)


Правила инициализации C++ довольно сложны. Они описаны во второй половине главы (пункта) 8 стандарта. Существует нулевая инициализация, прямая инициализация, инициализация значения, инициализация копирования, инициализация списка, и это лишь некоторые из них, и каждый из них может иметь различные взаимодействия в зависимости от контекста (объявление, параметр, возврат, бросок, инициализатор члена и т. д. ), свойства типа, который необходимо связать, и входное выражение инициализации или список инициализации в фигурных скобках. Разработчики языка также ставят перед собой цель обеспечить почти обратную совместимость с C и более ранними версиями C++, что ограничивает их возможности. Чтобы размышлять о последствиях изменений в правилах инициализации, требуется некоторое исследование, а изменения могут привести к множеству непредвиденных краевых случаев. Если вы заинтересованы, я рекомендую вам изучить стандарт и попытаться проработать последствия предлагаемого изменения, которое вы разработали.

person Andrew Tomazos    schedule 11.06.2013