如何将融合容器大小限制扩展到50以上?

时间:2014-10-14 08:05:44

标签: c++ boost boost-fusion

我想生成包含50个以上元素的boost fusion类型序列。 boost/fusion/container/vector/vector50.hpp的内容似乎暗示可能会以某种方式使用宏BOOST_FUSION_DONT_USE_PREPROCESSED_FILES来影响此限制。

我创建了以下简单程序,它将int推送到boost::fusion::vector类型指定的次数,然后将结果转换为向量(触发错误)。< / p>

#include <boost/fusion/container.hpp>                                              
#include <boost/fusion/algorithm.hpp>                                              

#include <type_traits>                                                             

template <typename Sequence, int N>                                                
struct PushBack                                                                    
{                                                                                  
    using type = typename PushBack<typename boost::fusion::result_of::push_back<Sequence, int>::type, N-1>::type;
};                                                                                 

template <typename Sequence>                                                       
struct PushBack<Sequence, 0>                                                       
{                                                                                  
    using type = Sequence;                                                         
};                                                                                 

int main()                                                                         
{                                                                                  
    using NullVector = boost::fusion::vector<>;                                    
    using Sequence = boost::fusion::result_of::as_vector<typename PushBack<NullVector, 20>::type>::type; // this line triggers the error

    Sequence s;                                                                    
    return 0;                                                                      
}                          

当我使用-D BOOST_FUSION_DONT_USE_PREPROCESSED_FILES -D FUSION_MAX_VECTOR_SIZE=100运行时,我遇到了大量错误,大致如下:

  

... / boost / fusion / container / generation / make_vector.hpp:105:25:错误:'vector51'没有命名类型   ... / boost / fusion / container / generation / make_vector.hpp:105:25:错误:'vector52'没有命名类型   ... / boost / fusion / container / generation / make_vector.hpp:105:25:错误:'vector ...'没有命名类型

显然,我做得不对。如何将此限制延长至50?我需要至少150 ......

3 个答案:

答案 0 :(得分:2)

这是一个两步法,首先在编译标志中定义:BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS,然后使用-DBOOST_MPL_LIMIT_VECTOR_SIZE=50 -DFUSION_MAX_VECTOR_SIZE=50(最接近的10)设置所需的大小

编辑:

即使您没有使用预处理的标题,但在标题中确实是运气不好,看起来它被这段代码限制为50:

#if (FUSION_MAX_VECTOR_SIZE > 40)
#include <boost/fusion/container/vector/vector50.hpp>
#endif

那真是愚蠢的事情:

#define BOOST_PP_FILENAME_1 <boost/fusion/container/vector/detail/vector_n.hpp>
#define BOOST_PP_ITERATION_LIMITS (41, 50)
#include BOOST_PP_ITERATE()

}}
嗯..我不认为除了修补之外还有其他方法。上面的代码..

EDIT2:嗯,如果有意图破解,显然有一种方法(无需修改提升),它确实附带了一个巨大的免责声明 - 正确测试,它编译,你可以访问超过50的元素,关于我将提供的所有保证......

#include <iostream>

#define BOOST_MPL_LIMIT_VECTOR_SIZE 50
#define FUSION_MAX_VECTOR_SIZE 60

// This sets us up with mpl vector up to 50
#include <boost/mpl/vector.hpp>

// This adds the missing chunk - you should be able to expand this up to template depth
// This sets up the sequence of vectors (vector1 : T + vector0 etc.
#include <boost/fusion/sequence/intrinsic/begin.hpp>
namespace boost { namespace mpl {

#   define BOOST_PP_ITERATION_PARAMS_1 \
    (3,(51, 60, <boost/mpl/vector/aux_/numbered.hpp>))
#   include BOOST_PP_ITERATE()

}}
// This sets up the specializations
#define AUX778076_SEQUENCE_BASE_NAME vector
#   define AUX778076_SEQUENCE_LIMIT BOOST_MPL_LIMIT_VECTOR_SIZE
#   define AUX778076_SEQUENCE_CONVERT_CN_TO(z,n,TARGET) TARGET(BOOST_PP_CAT(C,n))
#   include <boost/mpl/aux_/sequence_wrapper.hpp>

// Include everuthing up to vector50
#define BOOST_FUSION_DONT_USE_PREPROCESSED_FILES
#include <boost/fusion/container/vector/vector50.hpp>

// Add the missing range
namespace boost
{
namespace fusion
{
struct vector_tag;
#define BOOST_PP_FILENAME_1 <boost/fusion/container/vector/detail/vector_n.hpp>
#define BOOST_PP_ITERATION_LIMITS (51, 60)
#include BOOST_PP_ITERATE()
}
}

// Declare the vector class using the FUSION_MAX_VECTOR_SIZE, as the types themselves have been declared above, all is
// good in the world of fusion
#include <boost/fusion/container/vector/vector.hpp>


// Test access
#include <boost/fusion/sequence/intrinsic/at_c.hpp>


int main()
{

  using Sequence = typename boost::fusion::vector<
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    int,
    double,
    std::string,
    std::string
 >;

 Sequence s;

 std::cout << boost::fusion::at_c<51>(s) << std::endl;

}

基本上,我在上面所做的就是填充缺失的位(对于大于50的计数),但是根据需要实例化mpl和fusion的位。上述操作顺序非常严格,如果有人可以进一步提炼 - 请更新......

(注意:用gcc-4.8.2,boost-1.55,c ++ 11测试)

答案 1 :(得分:0)

在我看来,预处理文件只是编译时优化。

在这种情况下,您可能希望(?)大胆地前往以往没有人去过的地方:

  • 编辑该文件中的限制:

    namespace boost { namespace fusion
    {
        struct vector_tag;
        struct fusion_sequence_tag;
        struct random_access_traversal_tag;
    
    // expand vector41 to vector50
    #define BOOST_PP_FILENAME_1 <boost/fusion/container/vector/detail/vector_n.hpp>
    #define BOOST_PP_ITERATION_LIMITS (41, 100)
    #include BOOST_PP_ITERATE()
    
    }}
    
  • 以类似方式添加更多标题,例如vector60.hppvector70.hpp ...并将其包含在适当的位置

我没有测试过这个,但值得一试

答案 2 :(得分:0)

似乎没有可能在没有黑客入侵或使用boost wave预处理器的情况下扩展此限制,对我来说这两者都不是可行的选项。这里唯一真正的解决方案是使std::tuple使用mpl功能,并使用它而不是fusion容器。这个答案显示了如何做到这一点:

https://stackoverflow.com/a/15865204/1613983