在一行中使用两个折叠表达式
Use two fold expressions in one line
我正在学习 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>() );
}
will it work when we have variadic types, not indices ?
在那种情况下,只需将类型列表包装在可索引的类型元组中。
But is there a way to handle a few variadics via folds?
到目前为止,不,我不认为这是可能的;包总是线性扩展的,如果存在多个包,它们会同时扩展并且必须具有相同的长度,正如您已经观察到的那样。 'power-product' 包扩展没有 'direct' 语言支持。如果你想要一对模板参数的笛卡尔积,你总是会得到类似上面的东西......
我正在学习 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>() );
}
will it work when we have variadic types, not indices ?
在那种情况下,只需将类型列表包装在可索引的类型元组中。
But is there a way to handle a few variadics via folds?
到目前为止,不,我不认为这是可能的;包总是线性扩展的,如果存在多个包,它们会同时扩展并且必须具有相同的长度,正如您已经观察到的那样。 'power-product' 包扩展没有 'direct' 语言支持。如果你想要一对模板参数的笛卡尔积,你总是会得到类似上面的东西......