Search code examples
c++templatesboostboost-fusion

getting the structure name with boost fusion


Using boost::fusion is possible to iterate an adapted structure and get the name of each member of that structure.

Is there a way to retrieve also the name of the structure some way?

What I woulld like to do is the following: given the current scenario

namespace inner { 
struct test_struct {
  int a;
  int b;
} }

BOOST_FUSION_ADAPT_STRUCT( inner::test_struct, a, b );      

I'd like to have a function that will return "test_struct" (or "inner::test_struct" )

I did check the header file[*] containing struct_size and other extension classes but I haven't found any with that purpose.

Do you know if there is anything out there to do that?

[*] boost/fusion/adapted/struct/detail/extension.hpp


Solution

  • That's not a feature. You can see it by inspecting the output of the preprocessor.

    You can see the struct_member_name extension, but no such literals for the struct name:

    namespace boost {
        namespace fusion {
            namespace traits {
                template <> struct tag_of<inner::test_struct> { typedef struct_tag type; };
                template <> struct tag_of<inner::test_struct const> {
                    typedef struct_tag type;
                };
            } // namespace traits
            namespace extension {
                template <> struct access::struct_member<inner::test_struct, 0> {
                    struct deduced_attr_type {
                        static const inner::test_struct& obj;
                        typedef boost::type_of::remove_cv_ref_t<decltype(obj.a)> type;
                    };
                    typedef deduced_attr_type::type attribute_type;
                    typedef attribute_type type;
                    template <typename Seq> struct apply {
                        typedef typename add_reference<
                            typename mpl::eval_if<is_const<Seq>, add_const<attribute_type>,
                                     mpl::identity<attribute_type>>::type>::type
                                         type;
                        constexpr static type call(Seq& seq) { return seq.a; }
                    };
                };
                template <> struct struct_member_name<inner::test_struct, 0> {
                    typedef char const* type;
                    constexpr static type call() { return "a"; }
                };
                template <> struct access::struct_member<inner::test_struct, 1> {
                    struct deduced_attr_type {
                        static const inner::test_struct& obj;
                        typedef boost::type_of::remove_cv_ref_t<decltype(obj.b)> type;
                    };
                    typedef deduced_attr_type::type attribute_type;
                    typedef attribute_type type;
                    template <typename Seq> struct apply {
                        typedef typename add_reference<
                            typename mpl::eval_if<is_const<Seq>, add_const<attribute_type>,
                                     mpl::identity<attribute_type>>::type>::type
                                         type;
                        constexpr static type call(Seq& seq) { return seq.b; }
                    };
                };
                template <> struct struct_member_name<inner::test_struct, 1> {
                    typedef char const* type;
                    constexpr static type call() { return "b"; }
                };
                template <> struct struct_size<inner::test_struct> : mpl::int_<2> {};
                template <> struct struct_is_view<inner::test_struct> : mpl::false_ {};
            } // namespace extension
        } // namespace fusion
        namespace mpl {
            template <typename> struct sequence_tag;
            template <> struct sequence_tag<inner::test_struct> {
                typedef fusion::fusion_sequence_tag type;
            };
            template <> struct sequence_tag<inner::test_struct const> {
                typedef fusion::fusion_sequence_tag type;
            };
        } // namespace mpl
    } // namespace boost
    

    As always, it may not be too hard to add your own macro to get the extra information. See e.g. Parsing Selector struct with alternating tokens using Boost Spirit X3 or Boost fusion sequence type and name identification for structs and class