【问题标题】:C++: Forwarding the sum of parameter pack and a std::tuple/array [duplicate]C ++:转发参数包和std :: tuple / array的总和[重复]
【发布时间】:2014-04-12 01:45:30
【问题描述】:

我想实现类似于以下成员函数(方法)的东西,它应该通过与参数 index 对应的某个加法(加法)来增加每个参数,并且将其转发给另一个可变参数模板函数:

template<typename... Int> // a bunch of integral types (e.g. int, size_t, char)
void ForwardToFuncIncreased(Int... ints) {
   static_assert(sizeof...(Ints) == std::tuple_size<decltype(summands_)>::value,
                 "Incorrect number of integral types provided");

   Func( (ints + std::get<PARAM_INDEX(ints)>(summands_))... ); // failed attempt
}

其中summands_std::tuplestd::array 类型的成员变量(您可以假设其中之一)。基本要求是它应该没有运行时开销:

Func(int0 + std::get<0>(summands_), int1 + std::get<1>(summands_), ...);

(假设我为最多N 模板参数重载了函数)。

如果没有必要的运行时开销就不可能做到这一点,我愿意进行某些修改(尤其是在我的类中存储额外的东西或修改类型的方式)。

注意:我的目的不是提取模板参数索引,而是希望在没有它的情况下实现我所需要的。

【问题讨论】:

    标签: c++ c++11 variadic-templates template-meta-programming forwarding


    【解决方案1】:

    在 C++14 中,您将能够执行以下操作,与您最初的尝试非常相似:

    template<typename... Ns, size_t... Is>
    void ForwardToFuncIncreasedImpl(Ns... nums, std::index_sequence<Is...>)
    {
        Func( (nums + std::get<Is>(summands_))... );
    }
    
    template<typename... Ns>
    void ForwardToFuncIncreased(Ns... nums)
    {
        ForwardToFuncIncreasedImpl(nums..., std::index_sequence_for<Ns...>());
    }
    

    与此同时,您可以找到或编写自己的 index_sequence 实现。

    或者做这样的事情:首先做std::make_tuple(ints...),这样我们就有两个要求和的元组(或者一个元组和一个std::array)。然后使用 Andrei Alexandrescu 在The Way of the Exploding Tuple 中演示的模式将总和扩展为传递给Func 的参数包。

    template <int N>
    struct Pairwise;
    
    template <>
    struct Pairwise<0>
    {
        template <typename F, typename T, typename U, typename... Args>
        static void Sum(F f, T const&, U const&, Args... sums)
        {
            f(sums...);
        }
    };
    
    template <int N>
    struct Pairwise
    {
        template <typename F, typename T, typename U, typename... Args>
        static void Sum(F f, T const& a, U const& b, Args... sums)
        {
            Pairwise<N - 1>::Sum(f, a, b, std::get<N - 1>(a) + std::get<N - 1>(b), sums...);
        }
    };
    
    template <typename... Ns>
    void ForwardToFuncIncreased(Ns... nums)
    {
        Pairwise<sizeof...(Ns)>::Sum(Func, std::make_tuple(nums...), summands_);
    }
    

    也可以不用初始make_tuple

    template <typename... Ns>
    struct Pairwise;
    
    template <>
    struct Pairwise<>
    {
        template <typename F, typename T, typename... Args>
        static void Sum(F f, T const&, Args... sums)
        {
            f(sums...);
        }
    };
    
    template <typename N0, typename... Ns>
    struct Pairwise<N0, Ns...>
    {
        template <typename F, typename T, typename... Args>
        static void Sum(F f, N0 num0, Ns... nums, T const& a, Args&&... sums)
        {
            Pairwise<Ns...>::Sum(f, nums..., a, sums..., num0 + std::get<sizeof...(Args)>(a));
        }
    };
    
    template <typename... Ns>
    void ForwardToFuncIncreased(Ns... nums)
    {
        Pairwise<Ns...>::Sum(Func, nums..., summands_);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-08-08
      • 2012-05-23
      • 2015-04-11
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多