Конструктор списка инициализаторов с подготовкой к скобке

StackOverflow https://stackoverflow.com/questions/4118025

  •  29-09-2019
  •  | 
  •  

Вопрос

У меня есть фенотип класса со следующим конструктором:

Phenotype(uint8 init[NUM_ITEMS]);

Я могу создать такой фенотип, как это:

uint8 data[] = {0,0,0,0,0};
Phenotype p(data);

Но я получаю ошибку, когда пытаюсь создать ее как это:

Phenotype p = {0,0,0,0,0};

Выход:

$ make
g++ -Wall -g main.cpp -std=c++0x
main.cpp: In function ‘int main(int, char**)’:
main.cpp:109: error: no matching function for call to ‘Phenotype::Phenotype(<brace-enclosed initializer list>)’
main.cpp:37: note: candidates are: Phenotype::Phenotype(uint8*)

Похоже, что ошибка указывает на то, что существует способ определить конструктор, который берет список заинтересованных в скобке. Кто -нибудь знает, как это можно сделать?

Это было полезно?

Решение

Это может быть сделано только для агрегатов (массивы и определенные классы. Вопреки распространенному мнению, это работает и для многих непод). Написание конструктора, который их берет, невозможно.

Поскольку вы пометили его как «C ++ 0x», тогда это возможно. Волшебные слова-«конструктор-лист инициализатора». Это идет так

Phenotype(std::initializer_list<uint8> c) {
  assert(c.size() <= std::size(m_array));
  std::copy(c.begin(), c.end(), m_array);
}

// used like
Phenotype p1{1, 2, 3};
Phenotype p2({1, 3, 2}); // works too
Phenotype p3(1, 2, 3); // doesn't work

Однако такая инициализация будет по умолчанию построить массив, а затем использовать оператор назначения. Если вы стремитесь к скорости и безопасности (вы получаете ошибки времени компиляции для слишком большого количества инициализаторов!), Вы также можете использовать обычный конструктор с вариальным шаблоном.

Это может быть более общим, чем необходимо (часто достаточно инициализатор, особенно достаточно для простых целых чисел). Он получает выгоду от совершенного пересылки, так что аргумент RValue может быть построен в элемент массива

template<typename ...T>
Phenotype(T&&...t):m_array{ std::forward<T>(t)... } {

}

// used like
Phenotype p1{1, 2, 3}; 
Phenotype p2(1, 2, 3); // works too
Phenotype p3({1, 2, 3}); // doesn't work   

Это сложный выбор!

Редактировать Исправление, последний тоже работает, так как мы не делали конструктор explicit, поэтому он может использовать конструктор копирования Phenotype, построить временный Phenotype объект и скопируйте его на p3. Отказ Но это не то, что мы действительно хотели бы, чтобы звонки были :)

Другие советы

В C ++ 0x кажется, что вы можете создать конструктор для этого. У меня нет опыта с этим сам, но похоже, что это называется Список инициализатора-конструктор.

Контейнер может реализовать конструктор-списка инициализатора, как это:

template<class E> class vector {
public:
    vector (std::initializer_list<E> s) // initializer-list constructor
    {
        reserve(s.size());  // get the right amount of space
        uninitialized_copy(s.begin(), s.end(), elem);   // initialize elements (in elem[0:s.size()))
        sz = s.size();  // set vector size
    }

    // ... as before ...
};

Вам нужно использовать тип шаблона std :: initializer_list. Пример:

#include <iostream>
class X {
    public:
        X (std::initializer_list<int> list) {
        for (auto i = list.begin(); i != list.end(); i++) {
                std::cout << *i << std::endl;
            }
        }
};


int main () {
    X x = {1,2,3,4,5};
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top