Завершающая запятая в равномерной инициализации

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

std::vector< std::size_t > v1{5, }; // allowed syntax
std::vector< std::size_t > v2{10};

Можно ли использовать запятую, чтобы компилятор выбирал std::vector::vector(std::initializer_list< std::size_t >) конструктор вместо std::vector::vector(std::size_t, const std::size_t &) или есть другие хитрости с упомянутым синтаксисом?

Могу ли я использовать его, чтобы обнаружить, есть ли std::initializer_listперегрузка

Учитывая следующий код, какой конструктор должен быть выбран?

struct A { A(int) { ; } A(double, int = 3) { ; } };
A a{1};
A b{2, };

Этот код принятgcc 8 а также A(int) выбран в обоих случаях.

2 ответа

Решение

Во-первых, правила грамматики C++ делают конечный , необязательно для braced-init-list. Цитировать dcl.init/1

Декларатор может указать начальное значение для идентифицируемого идентификатора. Идентификатор обозначает инициализируемую переменную. Процесс инициализации, описанный в оставшейся части [dcl.init], применяется также к инициализациям, заданным другими синтаксическими контекстами, такими как инициализация параметров функции ([expr.call]) или инициализация возвращаемых значений ([stmt.return]).

initializer:
  brace-or-equal-initializer
  ( expression-list )
brace-or-equal-initializer:
  = initializer-clause
  braced-init-list
initializer-clause:
  assignment-expression
  braced-init-list
braced-init-list:
  { initializer-list ,opt }
  { designated-initializer-list ,opt }
  { }

Во-вторых, вы не можете переопределить систему разрешения перегрузки. Он всегда будет использовать std::initializer_list конструктор, если вы используете такой синтаксис и такой std::initializer_list конструктор доступен.

dcl.init.list / 2:

Конструктор является конструктором списка инициализаторов, если его первый параметр имеет тип std::initializer_list или ссылку на возможно cv-квалифицированный std::initializer_list для некоторого типа E, и либо нет других параметров, либо все остальные параметры имеют аргументы по умолчанию. [Примечание: конструкторы списка инициализатора предпочтительнее других конструкторов при инициализации списка ([over.match.list])....


Программа ниже печатает Using InitList:

#include <iostream>
#include <initializer_list>

struct X{
    X(std::initializer_list<double>){ std::cout << "Using InitList\n"; }
    X(int){ std::cout << "Using Single Arg ctor\n"; }
};

int main(){
    X x{5};
}

Несмотря на то, что 5 является литералом типа int, имело бы смысл выбрать конструктор с одним аргументом, так как он идеально подходит; и std::initializer_list<double> конструктор хочет список double, Тем не менее, правила благоприятствуют std::initializer_list<double> потому что это конструктор списка инициализатора.

В результате даже приведенная ниже программа дает сбой из-за сужения преобразования:

#include <iostream>
#include <initializer_list>

struct Y{
    Y(std::initializer_list<char>){ std::cout << "Y Using InitList\n"; }
    Y(int, int=4){ std::cout << "Y Using Double Arg ctor\n"; }
};

int main(){
    Y y1{4777};
    Y y2{577,};
    Y y3{57,7777};
}

В ответ на ваш комментарий ниже: " что если перегрузка std::initializer_list отсутствует или это не первый параметр конструктора? " - тогда разрешение перегрузки не выберет его. Демо-версия:

#include <iostream>
#include <initializer_list>

struct Y{
    Y(int, std::initializer_list<double>){ std::cout << "Y Using InitList\n"; }
    Y(int, int=4){ std::cout << "Y Using Double Arg ctor\n"; }
};

int main(){
    Y y1{4};
    Y y2{5,};
    Y y3{5,7};
}

Печать:

Y Using Double Arg ctor
Y Using Double Arg ctor
Y Using Double Arg ctor

Если нет доступного конструктора списка инициализаторов, тогда {initializer-list...,} Инициализатор в значительной степени возвращается к прямой инициализации согласно dcl.init/16, семантика которой описана в последующем абзаце dcl.init/16.

Нет. Эта запятая является концом, чтобы заставить трюки макроса препроцессора работать без ошибок компиляции. Это ничего не значит о вашем типе данных или его размере.

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