在C++ 0X中解压缩,函数应用程序和打包元组

sha*_*aki 2 c++ tuples functor c++11 iterable-unpacking

在不使用Boost的情况下,在以下代码中编写readvals函数的最佳方法是什么?基本上,它应该得到一个元组,调用它的elemets的特定函数,并将生成的结果再次作为元组返回.

是否有基于C++ 0X的元组Functor定义库?

template <class T>
struct A
{
    A(T _val):val(_val){}
    T ret() {return val;}
    T val;
};

template <typename... ARGS>
std::tuple<ARGS...> readvals(std::tuple<A<ARGS>...> targ)
{
    //???
}

int main(int argc, char **argv)
{
    A<int> ai = A<int>(5);
    A<char> ac = A<char>('c');
    A<double> ad = A<double>(0.5);


    std::tuple<A<int>,A<char>,A<double>> at = std::make_tuple(ai,ac,ad);

    // assuming proper overloading of "<<" for tuples exists
    std::cout << readvals<int,char,double>(at) << std::endl;
    // I expect something like (5, c, 0.5) in the output
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在SO上发现了一些问题,这些问题部分地解决了这个问题(元组解包,迭代元组元素等),但在我看来,与将所有这些解决方案放在一起相比,应该有一个更简单的解决方案.

Ker*_* SB 8

如果我理解正确,你只想创建一个新的元组,其内容是应用于旧元组内容的函数的结果?像这样:

std::tuple<A,B,C> result =
  std::tuple<A,B,C>(f(std::get<0>(x), f(std::get<1>(x), f(std::get<2>(x));
Run Code Online (Sandbox Code Playgroud)

这是正确的吗?为了回答这个问题,我正在窃取@Luc Danton的优秀元组索引器.从根本上说,这种结构允许我们写:

std::tuple<Args...> result = std::tuple<Args...>(f(std::get<Indices>(x))...);
Run Code Online (Sandbox Code Playgroud)

以下是它的工作原理:首先,Indices帮手:

#include <tuple>

template<int... Indices>
struct indices {
  typedef indices<Indices..., sizeof...(Indices)> next;
};

template<int Size>
struct build_indices {
  typedef typename build_indices<Size - 1>::type::next type;
};

template<>
struct build_indices<0> {
  typedef indices<> type;
};

template<typename Tuple>
typename build_indices<std::tuple_size<typename std::decay<Tuple>::type>::value>::type
make_indices()
{
  return {};
}
Run Code Online (Sandbox Code Playgroud)

现在为应用程序:我们只是创建一个简单,固定的功能f,使其输入加倍.

template <typename T> T f(const T & t) { return 2*t; }
Run Code Online (Sandbox Code Playgroud)

让我们将其应用于元组.这是一个硬连线功能,但你可以轻松地模板化f:

template <typename Tuple, int ...Indices>
Tuple apply_f_impl(const Tuple & x, indices<Indices...>)
{
  return Tuple(f(std::get<Indices>(x))...);
}

template <typename Tuple>
Tuple apply_f(const Tuple & x)
{
  return apply_f_impl(x, make_indices<Tuple>());
}
Run Code Online (Sandbox Code Playgroud)

最后,测试用例:

#include <iostream>
#include "prettyprint.hpp"

int main()
{
  std::tuple<int, double, char> x(5, 1.5, 'a');
  auto y = apply_f(x);

  std::cout << "Before: " << x << ", after: " << y << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

所有这些应归功于Luc,他提出了自我索引元组索引器.