Use expressions twice on the same line

I am learning C ++ fold expressions and it is really nice to deploy one package of parameters. But what if I need to expand several of them with one call?

I prepared one example to clarify what I mean:

#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; } 

My question is about this line:

 (Functor<ix, iy>::Execute(context), ...); 

In this particular example, it will be expanded for these calls:

 Functor<0, 0>::Execute(context) Functor<1, 1>::Execute(context) Functor<2, 2>::Execute(context) ... 

But I need it to call all combinations of ix and iy packages:

 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) ... 

I know that I can make an extra layer to walk through rows and columns (then twice in separate methods):

 #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; } 

But this method greatly complicates the reading of the code. Is it possible to do this trick with two folds on the same line?

+5
source share
1 answer

you can just write something like:

 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>() ); } 

Will it work when we have variable types, not indexes?

just wrap the type list in an indexable tuple type in this case.

But is there a way to handle multiple variations through creases?

at the moment, no, I do not think this is possible; packages always expand linearly, and if more than one package is present, they expand at the same time and should be the same length, as you already noticed. We do not have "direct" language support for the "power-product" package extensions. If you want the Cartesian product of a pair of template parameters, you always get something like the above ...

+4
source

Source: https://habr.com/ru/post/1273735/


All Articles