元组的可变参数生成

Variadic Generation of Tuples

本文关键字:参数 变参 元组      更新时间:2023-10-16

我想编写一个基于整数值和协调的 c++ 代码,生成一组元组和函数调用,如下所示:

// dimension = 1, input = (i) generated tuples: (i-1) (i), (i+1)
// dimension = 2, input = (i,j) generated tuples: (i-1, j), (i, j-1), (i, j),(i+1, j), (i, j+1)
<typename Index, int dimension>
void my_function(Index input)
{
    // some magic here that generates the following code or sth like this
    get_value(generated_tuple0);
    get_value(generated_tuple1);
    ....
    ....
    get_value(generated_tupleN);
}

我不擅长模板编程,也许在 C++11 中使用可变参数是可能的。

假设索引是一个元组,这是一个可能的解决方案:

template <class Index, int I, int dimension>
struct tuple_builder_t
{
    static void build(std::vector<Index> &result, Index center)
    {
        Index iter = center;
        for (int i = -1; i < 2; i++)
        {
            std::get<I - 1>(iter) = std::get<I - 1>(center) +i;
            tuple_builder_t<Index, I, dimension>::build(result,  iter);
        }
    }
};
template <class Index, int dimension>
struct tuple_builder_t<Index, dimension, dimension>
{
    static std::vector<Index> build(std::vector<Index> &result, Index center)
    {
        Index iter = center;
        for (int i = -1; i < 2; i++)
        {
            std::get<dimension - 1>(iter) = std::get<dimension - 1>(center) +i;
            result.push_back(iter);
        }
    }
};
template <class Index, int dimension>
void my_function(Index index)
{
    std::vector<Index> result;
    tuple_builder_t<Index, 1, dimension>::build(result, index);
}

这是一个巧妙的问题,我已经发现自己在类似的东西面前(迭代超立方体的维度)

这是一个编译时解决方案。它动态生成所需的元组,并使用这些元组调用传递的函数。

template<typename TupleType, typename FunctionType, size_t N, typename = std::enable_if_t<N != std::tuple_size<std::decay_t<TupleType> >::value> >  //why SFINAE required?
void tuple_caller_impl(TupleType&& t, FunctionType&& f, std::integral_constant<size_t, N>)
{
    --std::get<N>(t); f(t); ++std::get<N>(t);
    ++std::get<N>(t); f(t); --std::get<N>(t);
    tuple_caller_impl(std::forward<TupleType>(t), std::forward<FunctionType>(f), std::integral_constant<size_t, N+1>());
}
template<typename TupleType, typename FunctionType>
void tuple_caller_impl(TupleType&& t, FunctionType&& f, typename std::tuple_size<std::decay_t<TupleType> >::type)
{
    f(std::forward<TupleType>(t)); // finally call function on the unchanged tuple
                                   // could also be done by specializing the 0-th call to tuple_caller_impl
}
template<typename TupleType, typename FunctionType>
void tuple_caller(TupleType&& t, FunctionType&& f)
{
    tuple_caller_impl(std::forward<TupleType>(t), std::forward<FunctionType>(f), std::integral_constant<size_t, 0>());
}

像应用一样应用

int main()
{
    auto f = [](auto const& t) { std::cout<<"call function with ("<<std::get<0>(t)<<","<<std::get<1>(t)<<","<<std::get<2>(t)<<")"<<std::endl; };
    auto t= std::make_tuple(1,5,3);
    tuple_caller(t,f);
}

前面将以下内容打印到屏幕:

call function with (0,5,3)
call function with (2,5,3)
call function with (1,4,3)
call function with (1,6,3)
call function with (1,5,2)
call function with (1,5,4)
call function with (1,5,3)

演示

请注意,调用顺序与示例中的调用顺序不同。