списки символов и инициализаторов - PullRequest
2 голосов
/ 15 сентября 2010

Я хотел бы передать некоторые числовые байтовые значения через список инициализаторов шаблон с переменными числами в массив Это возможно?

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 ]

1 голос
/ 14 января 2011

Вам не нужен сложный код

template < int N > struct a {
  char s[N];
  template < typename ... A >
  a (A ... _a) : s {static_cast<char>(_a)...} {}
};
0 голосов
/ 16 сентября 2010

ПРИМЕЧАНИЕ. Все это не нужно, если вы не добавили функциональность в класс, чтобы он больше не был агрегатом. (Например, другие конструкторы, закрытые члены, базовый класс и т. Д.) Непосредственный способ исправить код в вопросе - просто удалить конструктор. Итак, давайте предположим, что есть что-то еще.

Я видел, как некоторые люди пытались делать такие вещи. Кажется уродливым иметь дело с семантикой преобразования и пытаться искусственно воссоздать функциональность обычного вызова функции.

Вот стратегия для создания класса массива, который просто имеет правильный конструктор.

Использование псевдонимов шаблонов может привести к обледенению торта, скрывая уродство ::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 );
}
0 голосов
/ 15 сентября 2010

Вы на самом деле не используете списки инициализатора. Конструктор получает шаблон переменной , и вы инициализируете x с равномерной инициализацией .

Единственная проблема в том, что я не знаю элегантного способа инициализации массива с initializer_list, AFAIK 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++;
    }
};
...