这个 boost::tuple 代码可以转换为纯 std:: 标准库代码吗?

is this boost::tuple code convertible to pure std:: standard library code?

提问人:kfmfe04 提问时间:12/20/2012 更新时间:12/22/2012 访问量:1686

问:

以下升压代码是否可以转换为纯 c++11 标准库?

我明白了,但我似乎不能让他们互相玩。std::tuplestd::for_each

我目前正在使用 gcc 4.7.2。

法典

#include <string>
#include <algorithm>
#include <iostream>

#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/boost_tuple.hpp>

struct DoOutput
{
    template<typename T>
    void operator()(T const& t) const
    {
            std::cerr << t << std::endl;
    }

    void operator()(std::string const& t) const
    {
            std::cerr << "'" << t << "'" << std::endl;
    }
};

int
main( int argc, char* argv[] )
{
    boost::tuple< std::string, int > t = boost::make_tuple( "foo", 42 );
    boost::fusion::for_each( t, DoOutput() );

    return 0;
}
C++ 提升 STL C++11 标准

评论


答:

4赞 Jonathan Wakely 12/20/2012 #1

不,代码不可直接转换。

Boost.Fusion 是一个用于处理元组的库,因此它适用于元组,即具有零个或多个异构类型的结构。 适用于迭代器范围,这些范围是同类类型的值范围。for_eachstd::for_each

使用类似 index_tuple.h 的东西,您可以将其更改为:

struct sink {
  template<typename... T>
    sink(T&&...) { }
};

template<typename T, typename F>
  int apply(T&& t, F& f)
  {
    f(std::forward<T>(t));
    return 0;
  }

template<typename Tuple, typename F, unsigned... Indices>
  void apply(Tuple&& t, F&& f, index_tuple<Indices...>)
  {
    sink{ apply(std::get<Indices>(std::forward<Tuple>(t)), f)... };
  }

int main()
{
  std::tuple< std::string, int > t = std::make_tuple( "foo", 42 );
  apply(t, DoOutput(), make_index_tuple<std::tuple_size<decltype(t)>::value>::type() );
}

这将创建一个类型并调用 ,该类型将参数包推导出为,然后将该包扩展为:index_tuple<0,1>applyIndices{0, 1}

sink{ apply(std::get<0>(t), f), apply(std::get<1>(t), f) };

其中 是 类型的函数对象,每个 apply 调用fDoOutputf(tn)

初始化临时值只是因为您无法在表达式中扩展参数包,例如,这是无效的:sink

    f(std::get<Indices>(t))...;

因此,相反,包作为初始值设定项列表扩展到对象的构造函数,这也保证了包扩展的每个元素都按顺序计算。

评论

3赞 Nawaz 12/20/2012
std::get<i>(t)不会编译。 需要是编译时常量。i
1赞 interjay 12/21/2012
请注意,(我相信)这并不能保证应用于元组元素的顺序。f
1赞 interjay 12/21/2012
另一个问题:返回时它不起作用,如上所述。fvoid
1赞 Jonathan Wakely 12/21/2012
使用间接级别进行修复,并使用包扩展作为初始化列表(从左到右计算)而不是函数参数列表
1赞 Jonathan Wakely 12/21/2012
@ildjarn,这只是说它为函数生成一个参数列表,而不是在扩展包后按哪个顺序计算参数。Clang++ 从左到右计算,但 G++ 不计算。
1赞 Mankarse 12/20/2012 #2

不。C++11 标准库不包括 的功能。你能希望的最好的事情是适应与以下方面的工作:boost::fusionstd::tupleboost::fusion

#include <string>
#include <algorithm>
#include <iostream>

#include <tuple>

#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/adapted/std_tuple.hpp> //This feature is undocumented

struct DoOutput
{
    template<typename T>
    void operator()(T const& t) const
    {
            std::cerr << t << std::endl;
    }

    void operator()(std::string const& t) const
    {
            std::cerr << "'" << t << "'" << std::endl;
    }
};

int
main( int argc, char* argv[] )
{
    std::tuple< std::string, int > t = std::make_tuple( "foo", 42 );
    boost::fusion::for_each( t, DoOutput() );

    return 0;
}

评论

0赞 alfC 7/27/2015
该功能现在已记录在案:boost.org/doc/libs/1_58_0/libs/fusion/doc/html/fusion/adapted/...