使用 std::get、std::tuple_size、std::tuple_element 对元组的组件求和 [英] Sum the components of a tuple up by using std::get, std::tuple_size, std::tuple_element

查看:32
本文介绍了使用 std::get、std::tuple_size、std::tuple_element 对元组的组件求和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义类,它有一个类似元组的接口.因为我希望我的代码尽可能通用,所以我认为将我的算法基于函数 std::getstd::tuple_size, std::tuple_element 所以你只需要专门化这些函数来使用我的算法.让我们将需要这些函数特化的概念称为 Tuple.

I've got a custom class that has a tuple-like interface. Because I want my code to be as generic as possible, I thought that it would be a good idea to base my algorithms on the functions std::get, std::tuple_size, std::tuple_element so you just have to specialize these functions to use my algorithms. Let's call the concept that requires these function specializations Tuple.

现在我正在尝试总结 Tuple 的组成部分.函数声明应该是这样的:

Now I am trying to sum up the components of a Tuple. The function declaration should be something like this:

template <class Tuple>
int sum_components(const Tuple& t);

我想这涉及到很多模板编程,但我就是不知道该怎么做.

I guess that there is a lot of template programming involved but I just can't figure out how to do it.

对于添加,我将只使用全局 + 运算符的重载.

For the addition I would just use an overload of the global + operator.

我正在使用 c++1z.

I am using c++1z.

推荐答案

这在 .

template<class Tuple>
decltype(auto) sum_components(Tuple const& tuple) {
  auto sum_them = [](auto const&... e)->decltype(auto) {
    return (e+...);
  };
  return std::apply( sum_them, tuple );
};

(...+e) 表示相反的折叠方向.

or (...+e) for the opposite fold direction.

在以前的版本中,正确的方法是编写自己的apply,而不是编写定制的实现.当您的编译器更新时,您可以删除代码.

In previous versions, the right approach would be to write your own apply rather than writing a bespoke implementation. When your compiler updates, you can then delete code.

,我可能会这样做:

In c++14, I might do this:

// namespace for utility code:
namespace utility {
  template<std::size_t...Is>
  auto index_over( std::index_sequence<Is...> ) {
    return [](auto&&f)->decltype(auto){
      return decltype(f)(f)( std::integral_constant<std::size_t,Is>{}... );
    };
  }
  template<std::size_t N>
  auto index_upto() {
    return index_over( std::make_index_sequence<N>{} );
  }
}
// namespace for semantic-equivalent replacements of `std` code:
namespace notstd {
  template<class F, class Tuple>
  decltype(auto) apply( F&& f, Tuple&& tuple ) {
    using dTuple = std::decay_t<Tuple>;
    auto index = ::utility::index_upto< std::tuple_size<dTuple>{} >();
    return index( [&](auto...Is)->decltype(auto){
      auto target=std::ref(f);
      return target( std::get<Is>( std::forward<Tuple>(tuple) )... );
    } ); 
  }
}

这非常接近 .(我滥用 std::ref 来获取 INVOKE 语义).(它不能完美地与右值调用程序一起工作,但这是非常极端的情况).

which is pretty close to std::apply in c++14. (I abuse std::ref to get INVOKE semantics). (It does not work perfectly with rvalue invokers, but that is very corner case).

,我建议此时升级你的编译器.在 我建议此时升级你的工作.

In c++11, I would advise upgrading your compiler at this point. In c++03 I'd advise upgrading your job at this point.

以上所有方法都进行左右折叠.在某些情况下,二叉树折叠可能会更好.这更棘手.

All of the above do right or left folds. In some cases, a binary tree fold might be better. This is trickier.

如果您的 + 使用表达式模板,则上述代码由于生命周期问题而无法正常工作.在某些情况下,您可能必须为之后,强制转换"添加另一种模板类型以使临时表达式树进行评估.

If your + does expression templates, the above code won't work well due to lifetime issues. You may have to add another template type for "afterwards, cast-to" to cause the temporary expression tree to evaluate in some cases.

这篇关于使用 std::get、std::tuple_size、std::tuple_element 对元组的组件求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆