Списки символов и инициализаторов
Я хотел бы передать некоторые числовые байтовые значения через список инициализаторов шаблон переменной в массив. Это возможно?
template < int N > struct a {
char s[N];
template < typename ... A >
a (A ... _a) : s {_a...} {}
};
int main () {
// g++-4.5: error: narrowing conversion of »_a#0« from »int« to »char« inside { }
a < 3 > x { 1, 2, 3 };
}
Что я могу думать о том,
- использовать восьмеричное представление, '\001' и т. д., или
- бросить каждое значение.
Но оба не удовлетворяют.
3 ответа
ПРИМЕЧАНИЕ. Все это не нужно, если вы не добавили функциональность в класс, чтобы он больше не был агрегатом. (Например, другие конструкторы, закрытые члены, базовый класс и т. Д.) Непосредственный способ исправить код в вопросе - просто удалить конструктор. Итак, давайте предположим, что есть что-то еще.
Я видел, как некоторые люди пытались делать такие вещи. Кажется уродливым иметь дело с семантикой преобразования и пытаться искусственно воссоздать функциональность обычного вызова функции.
Вот стратегия для создания класса массива, который просто имеет правильный конструктор.
Шаблон псевдонимов будет положить глазурь на торт, скрывая ::type
уродство, но это еще не в GCC.
template< typename ... NT >
struct var_ctor_array {
enum { size_e = 0 }; // only used for zero size case
};
template< typename T, typename ... NT >
struct var_ctor_array< T, NT ... > {
enum { size_e = 1 + sizeof...( NT ) };
T st[ size_e ];
var_ctor_array( T elem0, NT ... elemN )
: st { elem0, elemN ... } {}
};
template< typename T, size_t N, typename ... NT >
struct gen_var_ctor_array {
typedef typename gen_var_ctor_array< T, N-1, T, NT ... >::type type;
};
template< typename T, typename ... NT >
struct gen_var_ctor_array< T, 0, NT ... > {
typedef var_ctor_array< NT ... > type;
};
int main() { // usage
gen_var_ctor_array< char, 5 >::type five( 1, 2, 3, 4, 5 );
}
Вам не нужен сложный код
template < int N > struct a {
char s[N];
template < typename ... A >
a (A ... _a) : s {static_cast<char>(_a)...} {}
};
Вы на самом деле не используете списки инициализатора. Конструктор получает шаблон переменной, и вы инициализируете x
с равномерной инициализацией.
Единственная проблема в том, что я не знаю элегантного способа инициализации массива initializer_list
, НАСКОЛЬКО МНЕ ИЗВЕСТНО std::array
должен иметь конструктор, который принимает initializer_list
но он пока не поддерживается g++.
#include <utility>
template < int N > struct a {
char s[N];
a (std::initializer_list<char> list) {
if (N != list.size())
throw "list wrong size";
int i = 0;
const char* p = list.begin();
while(p != list.end())
s[i++] = *p++;
}
};