У меня есть класс Phenotype со следующим конструктором:
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*)
Ошибка, кажется, указывает на то, что есть способ определить конструктор, который принимает список инициализаторов, заключенный в фигурные скобки. Кто-нибудь знает, как это можно сделать?
Ответ 1 · рейтинг 72 · Johannes Schaub - litb
Это можно сделать только для агрегатов (массивов и определенных классов. Вопреки распространенному мнению, это работает и для многих не-подов). Написать конструктор, который их принимает, невозможно.
Поскольку вы пометили его как "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
Однако такая инициализация по умолчанию создает массив, а затем использует оператор присваивания. Если вы стремитесь к скорости и безопасности (вы получаете ошибки времени компиляции для слишком большого количества инициализаторов!), Вы также можете использовать обычный конструктор с вариативным шаблоном.
Это может быть более общим, чем необходимо (часто вполне достаточно initializer_list, особенно для простых целых чисел). Он выигрывает от идеальной пересылки, так что аргумент 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. Но это не то, что мы действительно хотели бы, чтобы звонки были :)
Ответ 2 · рейтинг 7 · Magnus Hoff
В 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 ...
};
Ответ 3 · рейтинг 4 · evnu
Вам необходимо использовать тип шаблона 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};
}