initializer_list в списке инициализации

Я хочу инициализировать базовый класс с помощью std::initializer_list.

struct A : public std::array<int, 4>
{
  // This constructor works fine
  A()
  : std::array<int, 4>{{ 1, 2, 3, 4 }}
  {
  }

  // THIS CONSTRUCTOR FAILS TO COMPILE
  A(std::initializer_list<int> il)
  : std::array<int, 4>{il}
  {
  }
};

Ошибка GCC для второго конструктора

ошибка: массив должен быть инициализирован с помощью инициализатора, заключенного в фигурные скобки

Я хочу инициализировать новый экземпляр A с помощью initializer_list, подобного этому

A var{{ 1, 2, 3, 4 }}

и передать его в базовый класс.


person user3528030    schedule 13.04.2014    source источник


Ответы (2)


В классе std::array нет конструктора, принимающего std::initializer_list.

Единственный способ сделать это так:

#include <array>
#include <initializer_list>

struct A : public std::array<int, 4>
{
    A()
    : std::array<int, 4>{{ 1, 2, 3, 4 }}
    {
    }

    A(std::array<int, 4> il)
    : std::array<int, 4>(il)
    {
    }
};

int main ()
{
    A a ({{ 1, 2, 3, 4 }});
}
person Chnossos    schedule 13.04.2014
comment
похоже, что std::initializer_list здесь неявно приводится к std::array. Повлияет ли это на производительность во время выполнения? - person user3528030; 13.04.2014
comment
Здесь используется не std::initializer_list: std::array использует aggregate_initialization . Цитирование cppreference : [std::array] сочетает в себе производительность и доступность массива в стиле C с преимуществами стандартного контейнера [...] - person Chnossos; 13.04.2014
comment
@Chnossos, хотя массив можно инициализировать с помощью инициализации списка, его нельзя инициализировать с помощью фактического объекта initializer_list. Попробуйте: auto il = {1,2,3}; array<int,3> a(il); - person ooga; 13.04.2014
comment
Так должны ли мы использовать агрегат_инициализацию для вещей фиксированного размера и инициализатор_список для вещей переменного размера? - person user3528030; 13.04.2014
comment
@ShitImplementor Вы можете использовать объект initializer_list, только если есть ctor, который его принимает. Что касается потери производительности, с конструкторами перемещения это не должно быть проблемой. - person ooga; 13.04.2014
comment
Итак, чтобы преодолеть это даже незначительное влияние на производительность, я мог бы также сделать std::array членом. Затем мне нужно было бы инициализировать тремя фигурными скобками, такими как A a{{{..}}};, и добавить обертку вокруг operator[], что является уродливым решением. - person user3528030; 13.04.2014
comment
Забудьте об этом влиянии на производительность. В настоящее время компиляторы достаточно умны, чтобы ускорить такие вещи. Меня больше беспокоит тот факт, что вы наследуете от стандартного контейнера. - person Chnossos; 13.04.2014
comment
Почему? Является ли наследование от контейнера плохой практикой? - person user3528030; 13.04.2014
comment
Да, это плохая практика. Я не буду подробно рассказывать в комментариях, поэтому вам лучше прочитать этот ответ. - person Chnossos; 13.04.2014
comment
Спасибо @Chnossos, этот ответ был полезен. - person user3528030; 16.04.2014

В нем говорится, что array можно инициализировать с помощью «инициализатора, заключенного в фигурные скобки», как в вашем первом ctor, но не с помощью initializer_list, как во втором. Нет массива ctor, который принимает initializer_list. На самом деле, для массивов нет ctors, за исключением неявно объявленных специальных функций-членов.

person ooga    schedule 13.04.2014