[Fusion] Associate arbitrary compile/runtime annotations with members of fusion sequence

Started to use Boost.Fusion in my project I quick realized that it would be very convenient if fusion adapt macroses like BOOST_FUSION_DEFINE_STRUCT would give ability to associate additional information with members. Second problem is that BOOST_FUSION_DEFINE_STRUCT and such doesn`t support inheritance. So I did a small utility library that allow to define fusion sequences with arbitrary list of annotations associated with each member, and want to share it with community :) http://tarasko.github.com/cppan/ Will appreciate for any comments

Hi, Documentation contains an error in the "Making class hierarchies": http://tarasko.github.com/cppan/cppan/tutorial.html#cppan.tutorial.making_cl... In the 'struct D' declared & annotated member 'd' of type 'int', but in example uses 'D::b3':
d.b3 = 30;
-- Regards, niXman ___________________________________________________ Dual-target(32 & 64-bit) MinGW compilers for 32 and 64-bit Windows: http://sourceforge.net/projects/mingwbuilds/ ___________________________________________________ Another online IDE: http://liveworkspace.org/

On 2/16/13 5:51 AM, Kozlov Taras wrote:
Started to use Boost.Fusion in my project I quick realized that it would be very convenient if fusion adapt macroses like BOOST_FUSION_DEFINE_STRUCT would give ability to associate additional information with members. Second problem is that BOOST_FUSION_DEFINE_STRUCT and such doesn`t support inheritance.
So I did a small utility library that allow to define fusion sequences with arbitrary list of annotations associated with each member, and want to share it with community :)
http://tarasko.github.com/cppan/
Will appreciate for any comments
Very interesting. I think that the extension to support inheritance is
nice. I would definitely love to see such adapters in Fusion. I'd
love to see both intrusive and non-intrusive adapters though, not just
the intrusive ones. As for the "annotations", well, that's a nice touch,
but I think that's best done by associating members with keys. If you
have a key, MK, for a member of type T, then you can write non-intrusive
traits such as:
traits::has_hash

17.02.2013 2:36, Joel de Guzman wrote:
On 2/16/13 5:51 AM, Kozlov Taras wrote:
Started to use Boost.Fusion in my project I quick realized that it would be very convenient if fusion adapt macroses like BOOST_FUSION_DEFINE_STRUCT would give ability to associate additional information with members. Second problem is that BOOST_FUSION_DEFINE_STRUCT and such doesn`t support inheritance.
So I did a small utility library that allow to define fusion sequences with arbitrary list of annotations associated with each member, and want to share it with community :)
http://tarasko.github.com/cppan/
Will appreciate for any comments
Very interesting. I think that the extension to support inheritance is nice. I would definitely love to see such adapters in Fusion. I'd love to see both intrusive and non-intrusive adapters though, not just the intrusive ones. As for the "annotations", well, that's a nice touch, but I think that's best done by associating members with keys. If you have a key, MK, for a member of type T, then you can write non-intrusive traits such as:
traits::has_hash
the biggest advantage with this approach is that it is open ended. You can add as much introspection 'traits' as you want anytime.
Regards,
Hi Joel,
Thanks for ideas on "annotations". I`m going to apply them, but first I
want to clearify some points, fix me were I`m wrong
1. Having structure A defined like following
struct A
{
CPPAN_DECLARE_AND_ANNOTATE(
((int, int_field_,
((int_annotation, 42))
((string_annotation, "Hello world"))
))
((std::string, string_field_,
((no_serialization, std::true_type()))
((no_hash, std::true_type()))
))
)
};
you want to see it as fusion Associative Sequence, where int_field_ will
have key type, something like A::key_int_field_, right?
2. Iterator for A struct will sequentally dereference to
fusion::pair

On 2/24/13 7:38 AM, Kozlov Taras wrote:
Hi Joel, Thanks for ideas on "annotations". I`m going to apply them, but first I want to clearify some points, fix me were I`m wrong
1. Having structure A defined like following struct A { CPPAN_DECLARE_AND_ANNOTATE( ((int, int_field_, ((int_annotation, 42)) ((string_annotation, "Hello world")) )) ((std::string, string_field_, ((no_serialization, std::true_type())) ((no_hash, std::true_type())) )) ) };
you want to see it as fusion Associative Sequence, where int_field_ will have key type, something like A::key_int_field_, right?
That's one way, alright. There can be other ways, but I haven't thought about them very well.
2. Iterator for A struct will sequentally dereference to fusion::pair
fusion::pair
Yep.
3. Members can be accessed directly or using fusion::at_key A a; at_key
(a);
Yep.
4. I guess the most straightforward way to assign runtime values for annotations is to make them as members in key type. struct A { struct key_int_field_ { int int_annotation; const char* string_annotation;
key_int_field_() : int_annotation(42), string_annotation("Hello world") {} }; ... }; Do you have any objections here?
A more generic approach is simply to treat annotations as just another
trait. That way, it can be a lot more flexible. You just specialize
a specific trait. Say traits::annotation_of
5. CPPAN_DEFINE_MEMBER_DETECTOR(no_hash); defines metafunction that will accept key type.
has_no_hash
Yep. Same.
This metafunction can be specialized for any other key type. Is it ok? The question arise because you wrote
traits::has_no_hash
where T - is member type MK - is key type
Forget what I said. Wit a member-key T is no longer needed.
I haven`t got the idea behind passing member type here, from my point of view, passing key type is sufficient. Could you explain it?
Agreed.
6. Regarding non-intrusive version. This should be something like
CPPAN_ADAPT_STRUCT_WITH_BASE( A, (base_type1)(base_type2) ((int, int_field_, ((int_annotation, 42)) ((string_annotation, "Hello world")) )) ((std::string, string_field_, ((no_serialization, std::true_type())) ((no_hash, std::true_type())) )) )
Right?
Looks good.
One thing bother me here, is it ok to define key type in namespace scope by CPPAN_ADAPT_STRUCT_WITH_BASE?
BOOST_FUSION_ADAPT_ASSOC_STRUCT and BOOST_FUSION_DEFINE_ASSOC_STRUCT go another way, it just takes structure name as parameter and left user to define key types itself. But I feel that when dealing with annotations this is not so convenient as inline annotations description in CPPAN_ADAPT_STRUCT_WITH_BASE.
I guess that's your call... unless (see below ***)
7. Generic question about adapt macroses in fusion.
I used BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF to define has_annotations metafunction that determine if type members were defined with CPPAN_DECLARE_AND_ANNOTATE. Then I wrote fusion extension which enables for arbitraty type if has_annotations<T> is true.
This approach allowed to move CPPAN_DECLARE_AND_ANNOTATE inside of struct definition.
Can BOOST_FUSION_DEFINE_STRUCT be reimplemented in that way? This will allow to get rid of namespaces sequence and struct_name parameters. I believe this will also make needless _TPL and _INLINE versions of BOOST_FUSION_DEFINE_STRUCT macroses.
Are there any compiler portability or design problems with such approach.
I'm not sure at the moment about the implications. If the tests pass, then that's a good indication that it's good. To be honest, the fusion macros need a lot of time, attention and love right now. I'm not quite happy with the way they are implemented, to be frank. Just reading the code drives me nuts! It seems that you know your way around the macros. If you could find a good way to clean them up, then we should talk. I'd love to see your extensions added, of course if you are interested in contributing and maintaining them; along with the other adapt/define macro- siblings. If you are interested, it would be crucial to have symmetry and uniformity. Thus to follow up on my answer above (***), if you intend to somehow have your code assimilated in fusion, then we cannot break the precedent and have a new way of doing things because that will confuse users. Regards, -- Joel de Guzman http://www.ciere.com http://boost-spirit.com http://www.cycfi.com/

24.02.2013 6:46, Joel de Guzman пишет:
7. Generic question about adapt macroses in fusion.
I used BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF to define has_annotations metafunction that determine if type members were defined with CPPAN_DECLARE_AND_ANNOTATE. Then I wrote fusion extension which enables for arbitraty type if has_annotations<T> is true.
This approach allowed to move CPPAN_DECLARE_AND_ANNOTATE inside of struct definition.
Can BOOST_FUSION_DEFINE_STRUCT be reimplemented in that way? This will allow to get rid of namespaces sequence and struct_name parameters. I believe this will also make needless _TPL and _INLINE versions of BOOST_FUSION_DEFINE_STRUCT macroses.
Are there any compiler portability or design problems with such approach.
I'm not sure at the moment about the implications. If the tests pass, then that's a good indication that it's good.
To be honest, the fusion macros need a lot of time, attention and love right now. I'm not quite happy with the way they are implemented, to be frank. Just reading the code drives me nuts! It seems that you know your way around the macros. If you could find a good way to clean them up, then we should talk.
I'd love to see your extensions added, of course if you are interested in contributing and maintaining them; along with the other adapt/define macro- siblings. If you are interested, it would be crucial to have symmetry and uniformity. Thus to follow up on my answer above (***), if you intend to somehow have your code assimilated in fusion, then we cannot break the precedent and have a new way of doing things because that will confuse users.
Regards,
Well, I guess most of people would be happy to contribute something usefull into Boost, and I`m not an exception here :) Here is how I see next generation of define and adapt macroses in fusion: 1. Intrusive. BOOST_FUSION_DECLARE_MEMBERS( (base_type0)(base_type1)..., (member_type0, member_name0) (member_type1, member_name1) ... ) BOOST_FUSION_DECLARE_ASSOC_MEMBERS( (base_type0)(base_type1)..., (member_type0, member_name0, key_type0) (member_type1, member_name1, key_type1) ... ) Example: struct name_key; struct age_key; struct D : B1, B2 { BOOST_FUSION_DECLARE_ASSOC_MEMBERS( (B1)(B2), (std::string, name_, name_key) (int, age_, age_key) ) }; I believe we can easily reimplement current adapt macroses BOOST_FUSION_DEFINE_STRUCT BOOST_FUSION_DEFINE_TPL_STRUCT BOOST_FUSION_DEFINE_STRUCT_INLINE BOOST_FUSION_DEFINE_TPL_STRUCT_INLINE BOOST_FUSION_DEFINE_ASSOC_STRUCT BOOST_FUSION_DEFINE_ASSOC_TPL_STRUCT on top of them Having BOOST_FUSION_DECLARE_ASSOC_MEMBERS will also make implementation of CPPAN_DECLARE_AND_ANNOTATE trivial. 2. Non-intrusive As far as I see, each BOOST_FUSION_ADAPT_* macro should have _WITH_BASE paired macro with additional base type sequence parameter. BOOST_FUSION_ADAPT_STRUCT_WITH_BASE( struct_name, (base_type0)(base_type1)..., (member_type0, member_name0) (member_type1, member_name1) ... ) I think I should move forward step by step: 1. Implement BOOST_FUSION_DECLARE_MEMBERS BOOST_FUSION_DECLARE_ASSOC_MEMBERS 2. Implement the most complex case from non-instrusive macroses. I guess that can be BOOST_FUSION_ADAPT_ASSOC_TPL_ADT_WITH_BASE Hope this will help to get complete view of common implementation details between instrusive and non-instrusive macroses. 3. Reimplement current instrusive macroses based on new BOOST_FUSION_DECLARE_MEMBERS 4. Other version of _WITH_BASE non-intrusive macroses 5. Trivial reimplementation of current non-intrusive macroses based on _WITH_BASE versions.

On 2/25/13 6:31 AM, Kozlov Taras wrote:
24.02.2013 6:46, Joel de Guzman пишет:
7. Generic question about adapt macroses in fusion.
I used BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF to define has_annotations metafunction that determine if type members were defined with CPPAN_DECLARE_AND_ANNOTATE. Then I wrote fusion extension which enables for arbitraty type if has_annotations<T> is true.
This approach allowed to move CPPAN_DECLARE_AND_ANNOTATE inside of struct definition.
Can BOOST_FUSION_DEFINE_STRUCT be reimplemented in that way? This will allow to get rid of namespaces sequence and struct_name parameters. I believe this will also make needless _TPL and _INLINE versions of BOOST_FUSION_DEFINE_STRUCT macroses.
Are there any compiler portability or design problems with such approach.
I'm not sure at the moment about the implications. If the tests pass, then that's a good indication that it's good.
To be honest, the fusion macros need a lot of time, attention and love right now. I'm not quite happy with the way they are implemented, to be frank. Just reading the code drives me nuts! It seems that you know your way around the macros. If you could find a good way to clean them up, then we should talk.
I'd love to see your extensions added, of course if you are interested in contributing and maintaining them; along with the other adapt/define macro- siblings. If you are interested, it would be crucial to have symmetry and uniformity. Thus to follow up on my answer above (***), if you intend to somehow have your code assimilated in fusion, then we cannot break the precedent and have a new way of doing things because that will confuse users.
Regards,
Well, I guess most of people would be happy to contribute something usefull into Boost, and I`m not an exception here :)
Here is how I see next generation of define and adapt macroses in fusion:
1. Intrusive.
BOOST_FUSION_DECLARE_MEMBERS( (base_type0)(base_type1)..., (member_type0, member_name0) (member_type1, member_name1) ... )
BOOST_FUSION_DECLARE_ASSOC_MEMBERS( (base_type0)(base_type1)..., (member_type0, member_name0, key_type0) (member_type1, member_name1, key_type1) ... )
Example:
struct name_key; struct age_key;
struct D : B1, B2 { BOOST_FUSION_DECLARE_ASSOC_MEMBERS( (B1)(B2), (std::string, name_, name_key) (int, age_, age_key) ) };
I believe we can easily reimplement current adapt macroses BOOST_FUSION_DEFINE_STRUCT BOOST_FUSION_DEFINE_TPL_STRUCT BOOST_FUSION_DEFINE_STRUCT_INLINE BOOST_FUSION_DEFINE_TPL_STRUCT_INLINE BOOST_FUSION_DEFINE_ASSOC_STRUCT BOOST_FUSION_DEFINE_ASSOC_TPL_STRUCT on top of them
Having BOOST_FUSION_DECLARE_ASSOC_MEMBERS will also make implementation of CPPAN_DECLARE_AND_ANNOTATE trivial.
2. Non-intrusive
As far as I see, each BOOST_FUSION_ADAPT_* macro should have _WITH_BASE paired macro with additional base type sequence parameter.
BOOST_FUSION_ADAPT_STRUCT_WITH_BASE( struct_name, (base_type0)(base_type1)..., (member_type0, member_name0) (member_type1, member_name1) ... )
I think I should move forward step by step:
1. Implement BOOST_FUSION_DECLARE_MEMBERS BOOST_FUSION_DECLARE_ASSOC_MEMBERS
2. Implement the most complex case from non-instrusive macroses. I guess that can be BOOST_FUSION_ADAPT_ASSOC_TPL_ADT_WITH_BASE
Hope this will help to get complete view of common implementation details between instrusive and non-instrusive macroses.
3. Reimplement current instrusive macroses based on new BOOST_FUSION_DECLARE_MEMBERS
4. Other version of _WITH_BASE non-intrusive macroses
5. Trivial reimplementation of current non-intrusive macroses based on _WITH_BASE versions.
Sounds wonderful! I'd also wish for a lot more tests, if you will :-) Let us follow up on this offline. Feel free to email me directly. Regards, -- Joel de Guzman http://www.ciere.com http://boost-spirit.com http://www.cycfi.com/
participants (3)
-
Joel de Guzman
-
Kozlov Taras
-
niXman