2010-11-30 68 views
0

我尝试了融合,发现了一些非常奇怪的东西......这里是代码...我已经突出显示有问题的代码// ############ TROUBLE HERE# #####提升融合奇数

#include <tr1/cstdint> 
#include <tr1/functional> 
#include <string> 
#include <iostream> 

// #define FUSION_MAX_VECTOR_SIZE 64 

#define BOOST_MPL_LIMIT_STRING_SIZE 128 

#include <boost/type_traits.hpp> 
#include <boost/mpl/string.hpp> 
#include <boost/fusion/algorithm.hpp> 
#include <boost/fusion/tuple.hpp> 
#include <boost/fusion/container/vector.hpp> 
#include <boost/fusion/container/generation.hpp> 
#include <boost/fusion/container/generation/vector_tie.hpp> 

typedef std::tr1::int32_t int32; 

typedef std::tr1::int64_t int64; 

template < class type_const_ref > 
struct remove_const_reference 
{ 
    typedef typename boost::remove_reference <type_const_ref>::type type_const; 
    typedef typename boost::remove_const <type_const>::type type; 
}; 

template < class T > 
class MetaClass; 

namespace fusion = boost::fusion; 

template < class T > 
struct ConstRefFieldMap 
{ 
    typedef typename MetaClass <T>::FieldNames FieldNames; 
    typedef typename MetaClass <T>::ConstRefFields ConstRefFields; 
    typedef typename boost::fusion::result_of::zip < FieldNames const, ConstRefFields const >::type type; 
}; 

template < class T > 
static typename MetaClass <T>::FieldNames fieldNames() 
{ 
    return typename MetaClass <T>::FieldNames(); 
} 

template < class T > 
static typename MetaClass <T>::ConstRefFields constRefFields(T const &obj) 
{ 
    return MetaClass <T>::constRefFields(obj); 
} 

template < class T > 
static typename ConstRefFieldMap <T>::type const constRefFieldMap(T const &obj) 
{ 
    return boost::fusion::zip(fieldNames <T>(), constRefFields(obj)); 
} 

class Currency 
{ 
    private: 
     typedef MetaClass <Currency> Meta; 

     friend class MetaClass <Currency>; 

    private: 
     std::string m_isoCode; 

     int32 m_rank; 

    public: 
     Currency(std::string const &isoCode, int32 const rank) 
     : m_isoCode(isoCode) 
     , m_rank(rank) 
     { 
     } 

     std::string const& getIsoCode() const 
     { 
      return m_isoCode; 
     } 

     int32 const getRank() const 
     { 
      return m_rank; 
     } 

    private: 
     void setIsoCode(std::string const &isoCode) 
     { 
      m_isoCode = isoCode; 
     } 

    public: 
     void setRank(int32 rank) 
     { 
      m_rank = rank; 
     } 
}; 

template <> 
class MetaClass <Currency> 
{ 
    public: 
     typedef Currency data_type; 

    public: 
     typedef std::string IsoCodeType; 

     typedef int32 RankType; 

     typedef boost::fusion::vector < 
      boost::mpl::string < 'i', 's', 'o', 'C', 'o', 'd', 'e' > 
     , boost::mpl::string < 'r', 'a', 'n', 'k' > 
     > FieldNames; 

     typedef boost::fusion::vector < 
      IsoCodeType & 
     , RankType & 
     > MutableRefFields; 

     typedef boost::fusion::vector < 
      IsoCodeType const & 
     , RankType const & 
     > ConstRefFields; 

     static MutableRefFields mutableRefFields(Currency &obj) 
     { 
      return MutableRefFields(obj.m_isoCode, obj.m_rank); 
     } 

     static ConstRefFields constRefFields(Currency const &obj) 
     { 
      return ConstRefFields(obj.m_isoCode, obj.m_rank); 
     } 

}; 

template < class T, class U > 
static typename ConstRefFieldMap <T>::type const constRefFieldMapTest(T const &obj, U const &u) 
{ 
    return boost::fusion::zip(fieldNames <T>(), u); 
} 

int main() 
{ 
    Currency const EUR("EUR", 500); 
    using boost::fusion::any; 

    { 
     std::cout << boost::fusion::at_c <0>(constRefFields(EUR)) << " : " << boost::fusion::at_c <1>(constRefFields(EUR)) << std::endl; 
     ConstRefFieldMap <Currency>::type const &fm = boost::fusion::zip(fieldNames <Currency>(), constRefFields(EUR)); 
// ############ TROUBLE HERE ###### 
//  ConstRefFieldMap <Currency>::type const &fm = constRefFieldMap(EUR); 
// ############ TROUBLE HERE ###### 
     { 
      { 
       typedef boost::fusion::result_of::at_c < ConstRefFieldMap <Currency>::type, 0 >::type field_value_type; 
       field_value_type const v = boost::fusion::at_c <0>(fm); 
       typedef boost::fusion::result_of::at_c < field_value_type, 0 >::type field_name_type; 
       field_name_type const n = boost::fusion::at_c <0>(v); 
       typedef boost::fusion::result_of::at_c < field_value_type, 1 >::type field_data_type; 
       field_data_type const d = boost::fusion::at_c <1>(v); 
       std::cout << boost::mpl::c_str < remove_const_reference <field_name_type>::type >::value << " : " << d << std::endl; 
      } 

      { 
       typedef boost::fusion::result_of::at_c < ConstRefFieldMap <Currency>::type, 1 >::type field_value_type; 
       field_value_type const v = boost::fusion::at_c <1>(fm); 
       typedef boost::fusion::result_of::at_c < field_value_type, 0 >::type field_name_type; 
       field_name_type const n = boost::fusion::at_c <0>(v); 
       typedef boost::fusion::result_of::at_c < field_value_type, 1 >::type field_data_type; 
       field_data_type const d = boost::fusion::at_c <1>(v); 
       std::cout << boost::mpl::c_str < remove_const_reference <field_name_type>::type >::value << " : " << d << std::endl; 
      } 
     } 
    } 
} 

我得到垃圾值或SIGSEGV,如果我使用constRefFieldMap()函数。如果我直接调用boost :: fusion :: zip,它可以很好地工作。下面是输出...

EUR : 500 
isoCode : EUR 
rank : 500 

我已经看过这个question早些时候...我正在运行到同样的问题在这里???

编辑1:

呈现什么,我试图做一个例子...

其实...我想写这样的代码。

MetaObject < Currency const > EUR_META(make_meta_object(EUR)); 
std::cout << get_field <std::string>("isoCode", EUR_META.constRefFieldMap()) << std::endl; 

MetaObject <Currency> GBP_META(make_meta_object(GBP)); 
MutableRefFieldMap <Currency>::type const &fm = GBP_META.mutableRefFieldMap(); 
std::cout << set_field("rank", fm, 497) << std::endl; 

访问者,我也可以通过字段名调用修饰符...

我打算写一个精神解析器解析JSON & XML和创建对象......从我的代码生成一些帮助。主要思想是避免为每个对象生成解析代码,但仅限于那些已使用的对象,并因此减少二进制大小。我现在有1000个物体。

我现在有这个工作。

+1

你会更好过只发布一个最小的测试案例,恐怕大块的代码吸引人走:) :) – 2010-12-01 07:26:16

回答

7

这很不幸,这个问题没有引起更多的关注,但我想大块代码没有多大帮助(以及模板元编程不太受欢迎的事实)。

无论如何,你是对的,这是一个类似的问题。

问题是,融合中的视图不复制参数,它们只保留对它们的引用。这使您可以通过中间值修改原始参数。

麻烦的是,在C++中,您被授权将临时绑定到const引用,并将临时生存期扩展为引用的临时生存期。然而,这种行为不是传递性的,导致了大量的麻烦。 (锵将尝试诊断这些情况,不幸的是,第一个补丁失败:P)

所以在这里你的问题是坐落在一个单行:

return boost::fusion::zip(fieldNames <T>(), constRefFields(obj)); 
  • fieldNames<T>()创建一个临时的,这势必会一个const引用,它的寿命延长,直到表达式的末尾:;
  • 当你回来时认为,临时寿命已到期,你持有到一个悬挂参考

快速修复:使fieldNames<T>()有一个本地静态变量并返回对此变量的引用,这将修复生存期问题。

我还是不明白你虽然曾试图什么,所以我真的不能给“更明智”的建议:)

+0

+1已经为*“我想大块代码没有什么帮助”* - 并通过它挖掘。 – peterchen 2010-12-01 08:32:14