【问题标题】:is this boost::tuple code convertible to pure std:: standard library code?这个 boost::tuple 代码可以转换为纯 std:: 标准库代码吗?
【发布时间】:2012-12-20 15:33:47
【问题描述】:

下面的 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;
}

【问题讨论】:

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


    【解决方案1】:

    不,代码不能直接转换。

    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&lt;0,1&gt; 并调用apply,它将参数包Indices 推导出为{0, 1},然后将该包扩展为:

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

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

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

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

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

    【讨论】:

    • std::get&lt;i&gt;(t) 不会编译。 i 需要是编译时常量。
    • 请注意(我相信)这并不能保证 f 应用于元组元素的顺序。
    • 另一个问题:当f 返回void 时,它不起作用,就像上面那样。
    • 修复了间接级别,并使用包扩展作为初始化列表(它确实从左到右评估)而不是函数参数列表
    • @ildjarn,这只是说它为函数生成一个参数列表,而不是在扩展包后评估参数的顺序。 Clang++ 从左到右计算,但 G++ 没有。
    【解决方案2】:

    没有。 C++11 标准库不包含boost::fusion 的功能。您可以期望的最好的结果是使 std::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;
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 2010-12-19
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多