2010-11-30 63 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