J'essaie Fusion et trouvé quelque chose de très étrange ... Voici le code ... J'ai mis en évidence le code problématique avec // ############ TROUBLE ICI # #####Boost fusion bizarrerie
#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;
}
}
}
}
Je reçois des valeurs de déchets ou SIGSEGV si j'utilise la fonction constRefFieldMap(). Si j'appelle directement boost :: fusion :: zip, cela fonctionne parfaitement. Voici la sortie ...
EUR : 500
isoCode : EUR
rank : 500
J'ai regardé ce question plus tôt ... que je courais dans le même problème ici ???
EDIT 1:
Présenter un exemple de ce que je suis en train de faire ...
En fait ... Je suis en train d'écrire du code comme celui-ci.
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;
accesseurs et modificateurs que je peux invoquer par des noms de terrain ...
je prévois d'écrire un analyseur d'esprit pour analyser XML JSON & et créer des objets ... avec l'aide de mes générateurs de code. L'idée principale est d'éviter de générer le code d'analyse pour chaque objet, mais seulement pour les objets qui sont utilisés et donc de réduire la taille binaire. J'ai des milliers d'objets maintenant.
Je travaille maintenant.
Vous auriez été mieux que l'affichage d'un cas de test minimal, je crains de gros morceaux de code attirent les gens :) –