3

下面的 boost 代码是否可以转换为纯 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;
}
4

2 回答 2

4

不,代码不能直接转换。

Boost.Fusion 是一个用于处理元组的库,因此它for_each可以处理元组,即具有零个或多个异构类型的结构。 std::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() );
}

这将创建一个 typeindex_tuple<0,1>和 calls apply,它将参数包推导出Indices{0, 1},然后将该包扩展为:

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

wheref是一个类型的函数对象DoOutput,并且每个 apply 调用f(tn)

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

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

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

于 2012-12-20T15:42:10.367 回答
1

不,C++11 标准库不包括boost::fusion. 您可以期望的最好的结果是适应与以下std::tuple人员一起工作boost::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;
}
于 2012-12-20T15:43:34.853 回答