Метод 1: va_args
Если вы согласны сделать бар POD, это можно сделать с помощью va_args
:
#include <stdarg.h>
struct bar {
void * ptr;
};
template<class T, int N>
struct foo
{
foo(...) { // here the arg list should be passed
va_list ap;
va_start(ap, N);
for (int i = 0; i < N; ++i) {
store[i] = va_arg(ap, T);
}
va_end(ap);
}
T store[N];
};
int main()
{
foo<bar,2> f(bar(),bar());
}
Хотя это и не здорово - вам нужно слишком сильно доверять вызывающему абоненту, и требование POD может быть весьма ограничивающим.
Метод 2: диапазон
Если вы согласны сделать ваш тип T
и конструируемым, и назначаемым по умолчанию, вы можете использовать этот метод:
#include <assert.h>
#include <stdlib.h>
struct bar {
bar(void * ptr): ptr(ptr) {}
bar() {}
void * ptr;
};
template<class T, int N>
struct foo
{
foo(T *begin, const T *end) { // here the arg list should be passed
// Normally I'd use std::copy here!
int i = 0;
while (begin != end) {
assert(i < N);
store[i] = *begin++;
}
}
T store[N];
};
int main()
{
bar b[2]={NULL,NULL};
foo<bar,2> f(&b[0], &b[sizeof(b)/sizeof(bar)]);
}
Это не совсем гладко - у вас есть и массив, и экземпляр вашего объекта, но вы можете сделать массив static const
и, по крайней мере, хорошо скрыть его от остальной части кода.
Способ 3: приемы перегрузки операторов
Вы также можете использовать трюк с operator,
, чтобы свести все элементы к одному параметру, что в IIRC аналогично тому, что делает Boost.Assign .