Я изучаю C ++ сложенные выражения, и они действительно хороши для расширения одного пакета параметров. Но что, если мне придется расширить несколько из них за один звонок?
Я подготовил один пример, чтобы уточнить, что я имею в виду:
#include <cstddef>
#include <iostream>
#include <utility>
template<
template<size_t ix_, size_t iy_> typename Functor,
typename FunctorContext,
size_t... ix,
size_t... iy>
void RepeatImpl(
FunctorContext* context,
std::index_sequence<ix...>,
std::index_sequence<iy...>)
{
(Functor<ix, iy>::Execute(context), ...);
}
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t width, size_t height,
typename FunctorContext>
void Repeat(FunctorContext* context)
{
RepeatImpl<Functor>(
context,
std::make_index_sequence<width>(),
std::make_index_sequence<height>());
}
template<size_t ix, size_t iy>
struct Init2dArrayFunctor
{
template<typename T>
static void Execute(T* array)
{
array[iy][ix] = 10;
}
};
int main(int, const char**)
{
constexpr size_t w = 10;
constexpr size_t h = 10;
int array[w][h] { 0 };
Repeat<Init2dArrayFunctor, w, h>(array);
for(size_t iy = 0; iy < h; ++iy)
{
for(size_t ix = 0; ix < w; ++ix)
{
std::cout << array[iy][ix] << ' ';
}
std::cout << std::endl;
}
return 0;
}
Мой вопрос об этой строке:
(Functor<ix, iy>::Execute(context), ...);
В этом конкретном примере он будет расширен до следующих вызовов:
Functor<0, 0>::Execute(context)
Functor<1, 1>::Execute(context)
Functor<2, 2>::Execute(context)
...
Но мне нужно это назвать все комбинации ix
а также iy
пакеты:
Functor<0, 0>::Execute(context)
Functor<0, 1>::Execute(context)
Functor<0, 2>::Execute(context)
...
Functor<1, 0>::Execute(context)
Functor<1, 1>::Execute(context)
Functor<1, 2>::Execute(context)
...
Я знаю, что могу сделать дополнительный слой, чтобы пройтись по строкам и столбцам (два выражения сложения в отдельных методах):
#include <cstddef>
#include <iostream>
#include <utility>template<
template<size_t ix_, size_t iy_> typename Functor,
size_t iRow,
typename FunctorContext,
size_t... iColumn>
void RepeatImpl_Row(
FunctorContext* context,
std::index_sequence<iColumn...>)
{
(Functor<iColumn, iRow>::Execute(context), ...);
}
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t columns,
typename FunctorContext,
size_t... iRow>
void RepeatImpl(
FunctorContext* context,
std::index_sequence<iRow...>)
{
(RepeatImpl_Row<Functor, iRow>(context, std::make_index_sequence<columns>()), ...);
}
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t width, size_t height,
typename FunctorContext>
void Repeat(FunctorContext* context)
{
RepeatImpl<Functor, width>(
context,
std::make_index_sequence<height>());
}
template<size_t ix, size_t iy>
struct Init2dArrayFunctor
{
template<typename T>
static void Execute(T* array)
{
array[iy][ix] = 10;
}
};
int main(int, const char**)
{
constexpr size_t w = 10;
constexpr size_t h = 10;
int array[w][h] { 0 };
Repeat<Init2dArrayFunctor, w, h>(array);
for(size_t iy = 0; iy < h; ++iy)
{
for(size_t ix = 0; ix < w; ++ix)
{
std::cout << array[iy][ix] << ' ';
}
std::cout << std::endl;
}
return 0;
}
Но этот способ делает код намного сложнее для чтения.
Может быть, можно сделать этот трюк с двумя выражениями сгиба в одной строке?
Вы можете просто написать что-то вроде:
template<
size_t height,
template<size_t ix_, size_t iy_> typename Functor,
typename FunctorContext,
size_t... ixy>
void RepeatImpl(
FunctorContext* context,
std::index_sequence<ixy...>)
{
(Functor< ixy / height, ixy % height >::Execute(context), ...);
}
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t width, size_t height,
typename FunctorContext>
void Repeat(FunctorContext* context)
{
RepeatImpl<height,Functor>(
context,
std::make_index_sequence<width*height>() );
}
это будет работать, когда у нас есть вариативные типы, а не индексы?
в этом случае просто оберните список типов в индексируемый кортеж типов.
Но есть ли способ справиться с несколькими вариантами сгибов?
на данный момент нет, я не думаю, что это возможно; Пакеты всегда расширяются линейно, и если присутствует более одной упаковки, они расширяются одновременно и должны иметь одинаковую длину, как вы уже заметили. У нас нет «прямой» языковой поддержки для расширений пакета «power-product». Если вы хотите получить декартово произведение пары параметров шаблона, у вас всегда будет что-то похожее на приведенное выше …
Других решений пока нет …