Шаблон для инициализатора переменной длины

Мне нужно семейство функций инициализатора с переменным количеством используемых значений. Я использую их для реализации операции сбора с библиотекой Eigen. Вот способ, которым я делаю это сейчас с одним шаблоном для каждой длины вектора:

template<typename T1, typename T2>
inline void gather (Array<T1,4,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,4,1> &index)
{
to << from[index[0]], from[index[1]], from[index[2]], from[index[3]];
}

template<typename T1, typename T2>
inline void gather (Array<T1,6,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,6,1> &index)
{
to << from[index[0]], from[index[1]], from[index[2]], from[index[3]], from[index[4]], from[index[5]];
}

Есть ли способ заменить длинный список шаблонов, как указано выше, с одним шаблоном, параметризованным параметром длины (4 и 6 в фрагменте выше)? Если да, то можно ли это сделать с помощью спецификаций языка до C ++ 11 (я использую Visual Studio 2010)?

Я хотел бы сохранить синтаксис значений, разделенных запятыми, так как я надеюсь, что в некоторых случаях он может привести к инициализации времени компиляции (const from а также index). Хотя я могу ошибаться в этом предположении. Список инициализаторов может иметь от 1 до 16 значений — нет необходимости беспокоиться о пустом списке.

1

Решение

Не используйте синтаксис инициализатора запятой в этом параметре, он будет громоздким. Этот синтаксис используется для удобства чтения при использовании литералов, что не соответствует вашему случаю.

Вместо этого я бы порекомендовал что-то вроде:

template<typename T1, typename T2, unsigned int SIZE, unsigned int INDEX>
struct gather {
gather(Array<T1,SIZE,1> &to,
const Array<T2,Dynamic,1> &from,
const Array<int,SIZE,1> &index)
{
to.col(INDEX) = from[index[INDEX]];
gather<T1,T2,SIZE,INDEX+1>(to,from, index);
}
};

template<typename T1, typename T2, unsigned int SIZE>
struct gather<T1,T2,SIZE,SIZE>{
gather(Array<T1,SIZE,1> &to,
const Array<T2,Dynamic,1> &from,
const Array<int,SIZE,1> &index)
{
}
};

который приятно производит тот же эффект, но статически (без цикла).

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

2

Другие решения

Это довольно сложно обобщить этот синтаксис на основе перегрузки operator, оператор, и результат выглядит в лучшем случае неловко (если он работает). Я бы порекомендовал попробовать другие варианты (например, пойти на MatrixBase::operator<<(DenseBase&) оператор).

Если вы все еще хотите, вы должны распаковать скаляры один за другим:

template<typename T1, typename T2, class CI, int Current, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Current>*)
{
gather(to, from, index, (ci,from[index[Current]]), (std::integral_constant<int, Current+1>*)0);
}

template<typename T1, typename T2, class CI, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Height>*) {}

template<typename T1, typename T2, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index) {
gather(to, from, index, (to << index[from[0]]), (std::integral_constant<int, 1>*)0);
}

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

Плюс, он имеет линейную глубину создания шаблона (и IMHO, что в этом случае неизбежно).

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector