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

时间:2012-12-20 15:33:47

标签: c++ boost stl c++11 std

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

我看到std::tuplestd::for_each,但我似乎无法让他们互相玩耍。

我目前正在使用gcc 4.7.2。

CODE

#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;
}

2 个答案:

答案 0 :(得分: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() );
}

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

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

其中fDoOutput类型的函数对象,每个都应用调用f(tn)

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

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

因此,将包作为初始化列表扩展为对象的构造函数,这也保证了包扩展的每个元素按顺序进行评估。

答案 1 :(得分: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;
}