Merge pull request #13 from daminetreg/fusion_adapters

BOOST_FUSION_ADAPT_ASSOC_STRUCT* deducing types
This commit is contained in:
Joel de Guzman
2014-07-30 06:03:39 +08:00
9 changed files with 250 additions and 95 deletions

View File

@ -193,7 +193,7 @@ __random_access_sequence__.
... ...
) )
// When BOOST_PP_VARIADICS is missing : // Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_STRUCT( BOOST_FUSION_ADAPT_STRUCT(
struct_name, struct_name,
(member_type0, member_name0) (member_type0, member_name0)
@ -211,8 +211,8 @@ The sequence of `member_nameN,` arguments or `(member_typeN, member_nameN)`
pairs declares the type and names of each of the struct members that are part of pairs declares the type and names of each of the struct members that are part of
the sequence. the sequence.
Omitting the type or using BOOST_FUSION_ADAPT_AUTO can be used to infer the type, When member_typeN is omitted or set to BOOST_FUSION_ADAPT_AUTO, the type is
as with decltype. infered with Boost.TypeOf.
The macro should be used at global scope, and `struct_name` should be the fully The macro should be used at global scope, and `struct_name` should be the fully
namespace qualified name of the struct to be adapted. namespace qualified name of the struct to be adapted.
@ -238,7 +238,7 @@ namespace qualified name of the struct to be adapted.
name, name,
age) age)
// When BOOST_PP_VARIADICS is missing : // Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_STRUCT( BOOST_FUSION_ADAPT_STRUCT(
demo::employee, demo::employee,
(BOOST_FUSION_ADAPT_AUTO, name) (BOOST_FUSION_ADAPT_AUTO, name)
@ -263,7 +263,7 @@ __random_access_sequence__.
... ...
) )
// When BOOST_PP_VARIADICS is missing : // Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_TPL_STRUCT( BOOST_FUSION_ADAPT_TPL_STRUCT(
(template_param0)(template_param1)..., (template_param0)(template_param1)...,
(struct_name) (specialization_param0)(specialization_param1)..., (struct_name) (specialization_param0)(specialization_param1)...,
@ -287,8 +287,8 @@ The sequence of `member_nameN,` arguments or `(member_typeN, member_nameN)`
pairs declares the type and names of each of the struct members that are part of pairs declares the type and names of each of the struct members that are part of
the sequence. the sequence.
Omitting the type or using BOOST_FUSION_ADAPT_AUTO can be used to infer the type, When member_typeN is omitted or set to BOOST_FUSION_ADAPT_AUTO, the type is
as with decltype. infered with Boost.TypeOf.
The macro should be used at global scope, and `struct_name` should be the fully The macro should be used at global scope, and `struct_name` should be the fully
namespace qualified name of the struct to be adapted. namespace qualified name of the struct to be adapted.
@ -355,7 +355,7 @@ adapted using the given name.
... ...
) )
// When BOOST_PP_VARIADICS is missing : // Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_STRUCT_NAMED( BOOST_FUSION_ADAPT_STRUCT_NAMED(
struct_name, adapted_name, struct_name, adapted_name,
@ -393,8 +393,8 @@ The sequence of `member_nameN,` arguments or `(member_typeN, member_nameN)`
pairs declares the type and names of each of the struct members that are part of pairs declares the type and names of each of the struct members that are part of
the sequence. the sequence.
Omitting the type or using BOOST_FUSION_ADAPT_AUTO can be used to infer the type, When member_typeN is omitted or set to BOOST_FUSION_ADAPT_AUTO, the type is
as with decltype. infered with Boost.TypeOf.
The macros should be used at global scope, and `struct_name` should be the fully The macros should be used at global scope, and `struct_name` should be the fully
namespace qualified name of the struct to be converted. namespace qualified name of the struct to be converted.
@ -421,7 +421,7 @@ namespace qualified name of the struct to be converted.
name, name,
age) age)
// When BOOST_PP_VARIADICS is missing : // Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_STRUCT_NAMED( BOOST_FUSION_ADAPT_STRUCT_NAMED(
demo::employee, adapted_employee, demo::employee, adapted_employee,
(BOOST_FUSION_ADAPT_AUTO, name), (BOOST_FUSION_ADAPT_AUTO, name),
@ -439,8 +439,8 @@ __random_access_sequence__ and __associative_sequence__.
[heading Synopsis] [heading Synopsis]
BOOST_FUSION_ADAPT_ASSOC_STRUCT( BOOST_FUSION_ADAPT_ASSOC_STRUCT(
struct_name, struct_name,
(member_type0, member_name0, key_type0) ([member_type0,] member_name0, key_type0)
(member_type1, member_name1, key_type1) ([member_type1,] member_name1, key_type1)
... ...
) )
@ -448,10 +448,13 @@ __random_access_sequence__ and __associative_sequence__.
The above macro generates the necessary code to adapt `struct_name` The above macro generates the necessary code to adapt `struct_name`
as a model of __random_access_sequence__ and __associative_sequence__. as a model of __random_access_sequence__ and __associative_sequence__.
The sequence of `(member_typeN, member_nameN, key_typeN)` The sequence of `([member_typeN,] member_nameN, key_typeN)` tuples
triples declares the type, name and key type of each of the struct members declares the type, name and key type of each of the struct members
that are part of the sequence. that are part of the sequence.
When member_typeN is omitted or set to BOOST_FUSION_ADAPT_AUTO, the type is
infered with Boost.TypeOf.
The macro should be used at global scope, and `struct_name` should be the fully The macro should be used at global scope, and `struct_name` should be the fully
namespace qualified name of the struct to be adapted. namespace qualified name of the struct to be adapted.
@ -481,8 +484,14 @@ namespace qualified name of the struct to be adapted.
// keys keys::name and keys::age present. // keys keys::name and keys::age present.
BOOST_FUSION_ADAPT_ASSOC_STRUCT( BOOST_FUSION_ADAPT_ASSOC_STRUCT(
demo::employee, demo::employee,
(std::string, name, keys::name) (name, keys::name)
(int, age, keys::age)) (age, keys::age))
// Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_ASSOC_STRUCT(
demo::employee,
(BOOST_FUSION_ADAPT_AUTO, name, keys::name),
(BOOST_FUSION_ADAPT_AUTO, age, keys::name))
[endsect] [endsect]
@ -497,8 +506,8 @@ __random_access_sequence__ and __associative_sequence__.
BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT( BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT(
(template_param0)(template_param1)..., (template_param0)(template_param1)...,
(struct_name) (specialization_param0)(specialization_param1)..., (struct_name) (specialization_param0)(specialization_param1)...,
(member_type0, member_name0, key_type0) ([member_type0,] member_name0, key_type0)
(member_type1, member_name1, key_type1) ([member_type1,] member_name1, key_type1)
... ...
) )
@ -512,10 +521,13 @@ the template type parameters used.
The sequence `(specialization_param0)(specialization_param1)...` The sequence `(specialization_param0)(specialization_param1)...`
declares the template parameters of the actual specialization of `struct_name` declares the template parameters of the actual specialization of `struct_name`
that is adapted as a fusion sequence. that is adapted as a fusion sequence.
The sequence of `(member_typeN, member_nameN, key_typeN)` The sequence of `([member_typeN,] member_nameN, key_typeN)`
triples declares the type, name and key type of each of the struct members tuples declares the type, name and key type of each of the struct members
that are part of the sequence. that are part of the sequence.
When member_typeN is omitted or set to BOOST_FUSION_ADAPT_AUTO, the type is
infered with Boost.TypeOf.
The macro should be used at global scope, and `struct_name` should be the fully The macro should be used at global scope, and `struct_name` should be the fully
namespace qualified name of the struct to be adapted. namespace qualified name of the struct to be adapted.
@ -544,6 +556,13 @@ namespace qualified name of the struct to be adapted.
// Any instantiated demo::employee is now a Fusion sequence. // Any instantiated demo::employee is now a Fusion sequence.
// It is also an associative sequence with // It is also an associative sequence with
// keys keys::name and keys::age present. // keys keys::name and keys::age present.
BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT(
(Name)(Age),
(demo::employee) (Name)(Age),
(name, keys::name)
(age, keys::age))
// Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT( BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT(
(Name)(Age), (Name)(Age),
(demo::employee) (Name)(Age), (demo::employee) (Name)(Age),
@ -563,8 +582,8 @@ __associative_sequence__. The given struct is adapted using the given name.
[heading Synopsis] [heading Synopsis]
BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED( BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED(
struct_name, adapted_name, struct_name, adapted_name,
(member_type0, member_name0, key_type0) ([member_type0,] member_name0, key_type0)
(member_type1, member_name1, key_type1) ([member_type1,] member_name1, key_type1)
... ...
) )
@ -572,8 +591,8 @@ __associative_sequence__. The given struct is adapted using the given name.
struct_name, struct_name,
(namespace0)(namespace1)..., (namespace0)(namespace1)...,
adapted_name, adapted_name,
(member_type0, member_name0, key_type0) ([member_type0,] member_name0, key_type0)
(member_type1, member_name1, key_type1) ([member_type1,] member_name1, key_type1)
... ...
) )
@ -593,6 +612,9 @@ The sequence of `(member_typeN, member_nameN, key_typeN)`
triples declares the type, name and key type of each of the struct members triples declares the type, name and key type of each of the struct members
that are part of the sequence. that are part of the sequence.
When member_typeN is omitted or set to BOOST_FUSION_ADAPT_AUTO, the type is
infered with Boost.TypeOf.
The macros should be used at global scope, and `struct_name` should be the fully The macros should be used at global scope, and `struct_name` should be the fully
namespace qualified name of the struct to be converted. namespace qualified name of the struct to be converted.
@ -621,8 +643,14 @@ namespace qualified name of the struct to be converted.
// referring to demo::employee // referring to demo::employee
BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED( BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED(
demo::employee, adapted_employee, demo::employee, adapted_employee,
(std::string, name, keys::name) (name, keys::name)
(int, age, keys::age)) (age, keys::age))
// Without BOOST_PP_VARIADICS support :
BOOST_FUSION_ADAPT_ASSOC_STRUCT_NAMED(
demo::employee, adapted_employee,
(BOOST_FUSION_ADAPT_AUTO, name, keys::name)
(BOOST_FUSION_ADAPT_AUTO, age, keys::age))
[endsect] [endsect]

View File

@ -21,6 +21,7 @@
#include <boost/fusion/adapted/struct/detail/extension.hpp> #include <boost/fusion/adapted/struct/detail/extension.hpp>
#include <boost/fusion/adapted/struct/detail/adapt_base.hpp> #include <boost/fusion/adapted/struct/detail/adapt_base.hpp>
#include <boost/fusion/adapted/struct/detail/adapt_base_assoc_attr_filler.hpp>
#include <boost/fusion/adapted/struct/detail/at_impl.hpp> #include <boost/fusion/adapted/struct/detail/at_impl.hpp>
#include <boost/fusion/adapted/struct/detail/is_view_impl.hpp> #include <boost/fusion/adapted/struct/detail/is_view_impl.hpp>
#include <boost/fusion/adapted/struct/detail/is_sequence_impl.hpp> #include <boost/fusion/adapted/struct/detail/is_sequence_impl.hpp>
@ -35,25 +36,27 @@
#include <boost/fusion/adapted/struct/detail/key_of_impl.hpp> #include <boost/fusion/adapted/struct/detail/key_of_impl.hpp>
#include <boost/fusion/adapted/struct/detail/value_of_data_impl.hpp> #include <boost/fusion/adapted/struct/detail/value_of_data_impl.hpp>
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0(X, Y, Z) \
((X, Y, Z)) BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1(X, Y, Z) \
((X, Y, Z)) BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0_END
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1_END
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_C_BASE( \ #define BOOST_FUSION_ADAPT_ASSOC_STRUCT_C_BASE( \
TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW,I,PREFIX,ATTRIBUTE) \ TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW,I,PREFIX,ATTRIBUTE) \
\ \
BOOST_FUSION_ADAPT_STRUCT_C_BASE( \ BOOST_FUSION_ADAPT_STRUCT_C_BASE( \
TEMPLATE_PARAMS_SEQ, NAME_SEQ, IS_VIEW, I, PREFIX, ATTRIBUTE, 3) \ TEMPLATE_PARAMS_SEQ, \
NAME_SEQ, \
IS_VIEW, \
I, \
PREFIX, \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR(ATTRIBUTE), \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
BOOST_PP_IF(BOOST_PP_LESS( \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE),3), 1, 0)) \
\ \
template< \ template< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \
> \ > \
struct struct_assoc_key<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ), I> \ struct struct_assoc_key<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ), I> \
{ \ { \
typedef BOOST_PP_TUPLE_ELEM(3, 2, ATTRIBUTE) type; \ typedef \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAPPEDATTR_GET_KEY(ATTRIBUTE) type; \
}; };
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_C( \ #define BOOST_FUSION_ADAPT_ASSOC_STRUCT_C( \
@ -62,6 +65,7 @@
BOOST_FUSION_ADAPT_ASSOC_STRUCT_C_BASE( \ BOOST_FUSION_ADAPT_ASSOC_STRUCT_C_BASE( \
TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW,I,BOOST_PP_EMPTY,ATTRIBUTE) TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW,I,BOOST_PP_EMPTY,ATTRIBUTE)
#define BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT( \ #define BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT( \
TEMPLATE_PARAMS_SEQ, NAME_SEQ, ATTRIBUTES) \ TEMPLATE_PARAMS_SEQ, NAME_SEQ, ATTRIBUTES) \
\ \

View File

@ -43,10 +43,11 @@
I, \ I, \
BOOST_PP_IF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \ BOOST_PP_IF(IS_VIEW, BOOST_FUSION_PROXY_PREFIX, BOOST_PP_EMPTY), \
BOOST_PP_TUPLE_ELEM(2, 1, ATTRIBUTE), \ BOOST_PP_TUPLE_ELEM(2, 1, ATTRIBUTE), \
BOOST_PP_TUPLE_ELEM(2, 0, ATTRIBUTE)) BOOST_PP_TUPLE_ELEM(2, 0, ATTRIBUTE), \
BOOST_PP_IF( \
BOOST_PP_LESS(BOOST_PP_TUPLE_ELEM(2, 0, ATTRIBUTE),2), 1, 0))
#define BOOST_FUSION_ADAPT_AUTO BOOST_PP_EMPTY()
#if BOOST_PP_VARIADICS #if BOOST_PP_VARIADICS

View File

@ -12,6 +12,13 @@
#include <boost/fusion/adapted/struct/adapt_assoc_struct.hpp> #include <boost/fusion/adapted/struct/adapt_assoc_struct.hpp>
#include <boost/fusion/adapted/struct/detail/define_struct.hpp> #include <boost/fusion/adapted/struct/detail/define_struct.hpp>
#define BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_0(X, Y, Z) \
((X, Y, Z)) BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_1
#define BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_1(X, Y, Z) \
((X, Y, Z)) BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_0
#define BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_0_END
#define BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_1_END
#define BOOST_FUSION_DEFINE_ASSOC_TPL_STRUCT( \ #define BOOST_FUSION_DEFINE_ASSOC_TPL_STRUCT( \
TEMPLATE_PARAMS_SEQ, NAMESPACE_SEQ, NAME, ATTRIBUTES) \ TEMPLATE_PARAMS_SEQ, NAMESPACE_SEQ, NAME, ATTRIBUTES) \
\ \
@ -20,7 +27,7 @@
(0)NAMESPACE_SEQ, \ (0)NAMESPACE_SEQ, \
NAME, \ NAME, \
BOOST_PP_CAT( \ BOOST_PP_CAT( \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0(0,0,0)ATTRIBUTES,_END), \ BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_0(0,0,0)ATTRIBUTES,_END), \
3) \ 3) \
\ \
BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT( \ BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT( \
@ -34,7 +41,7 @@
(0)NAMESPACE_SEQ, \ (0)NAMESPACE_SEQ, \
NAME, \ NAME, \
BOOST_PP_CAT( \ BOOST_PP_CAT( \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0(0,0,0)ATTRIBUTES,_END), \ BOOST_FUSION_DEFINE_ASSOC_STRUCT_FILLER_0(0,0,0)ATTRIBUTES,_END), \
3) \ 3) \
\ \
BOOST_FUSION_ADAPT_ASSOC_STRUCT( \ BOOST_FUSION_ADAPT_ASSOC_STRUCT( \

View File

@ -35,6 +35,8 @@
#include <boost/typeof/typeof.hpp> #include <boost/typeof/typeof.hpp>
#define BOOST_FUSION_ADAPT_AUTO BOOST_PP_EMPTY()
#define BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME_TEMPLATE_PARAMS(SEQ) \ #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME_TEMPLATE_PARAMS(SEQ) \
BOOST_PP_SEQ_HEAD(SEQ)<BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TAIL(SEQ))> \ BOOST_PP_SEQ_HEAD(SEQ)<BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TAIL(SEQ))> \
BOOST_PP_EMPTY() BOOST_PP_EMPTY()
@ -124,7 +126,8 @@
#define BOOST_FUSION_ADAPT_STRUCT_C_BASE( \ #define BOOST_FUSION_ADAPT_STRUCT_C_BASE( \
TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW, \ TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW, \
I,PREFIX,ATTRIBUTE,ATTRIBUTE_TUPEL_SIZE) \ I,PREFIX,ATTRIBUTE,ATTRIBUTE_TUPEL_SIZE, \
DEDUCE_TYPE) \
\ \
template< \ template< \
BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \
@ -135,7 +138,7 @@
> \ > \
{ \ { \
typedef \ typedef \
BOOST_PP_IF(BOOST_PP_LESS(ATTRIBUTE_TUPEL_SIZE,2), \ BOOST_PP_IF(DEDUCE_TYPE, \
BOOST_FUSION_ATTRIBUTE_TYPEOF, BOOST_FUSION_ATTRIBUTE_GIVENTYPE \ BOOST_FUSION_ATTRIBUTE_TYPEOF, BOOST_FUSION_ATTRIBUTE_GIVENTYPE \
)(NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX) \ )(NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX) \
attribute_type; \ attribute_type; \
@ -163,8 +166,7 @@
{ \ { \
return seq.PREFIX() \ return seq.PREFIX() \
BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \
BOOST_PP_IF(BOOST_PP_LESS(ATTRIBUTE_TUPEL_SIZE,2), 0, 1),\ BOOST_PP_IF(DEDUCE_TYPE, 0, 1), ATTRIBUTE); \
ATTRIBUTE); \
} \ } \
}; \ }; \
}; \ }; \
@ -185,7 +187,7 @@
{ \ { \
return BOOST_PP_STRINGIZE( \ return BOOST_PP_STRINGIZE( \
BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \
BOOST_PP_IF(BOOST_PP_LESS(ATTRIBUTE_TUPEL_SIZE,2), 0, 1),\ BOOST_PP_IF(DEDUCE_TYPE, 0, 1), \
ATTRIBUTE)); \ ATTRIBUTE)); \
} \ } \
}; };

View File

@ -0,0 +1,62 @@
/*=============================================================================
Copyright (c) 2013-2014 Damien Buhl
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_BASE_ASSOC_ATTR_FILLER_HPP
#define BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_BASE_ASSOC_ATTR_FILLER_HPP
#include <boost/config.hpp>
#include <boost/fusion/adapted/struct/detail/adapt_base_attr_filler.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/facilities/is_empty.hpp>
#if BOOST_PP_VARIADICS
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0(...) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(__VA_ARGS__) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1(...) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(__VA_ARGS__) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(...) \
((BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), (__VA_ARGS__)))
#else
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0(X, Y, Z) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(X, Y, Z) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1(X, Y, Z) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(X, Y, Z) \
BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAP_ATTR(X, Y, Z) \
BOOST_PP_IF(BOOST_PP_IS_EMPTY(X), \
((2, (Y,Z))), \
((3, (X,Y,Z))) \
)
#endif
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_0_END
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLER_1_END
#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_WRAPPEDATTR_GET_KEY(ATTRIBUTE) \
BOOST_PP_TUPLE_ELEM( \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), \
BOOST_PP_SUB(BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE), 1), \
BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR(ATTRIBUTE))
#endif

View File

@ -12,44 +12,52 @@
#include <boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp> #include <boost/fusion/adapted/struct/detail/preprocessor/is_seq.hpp>
#include <boost/preprocessor/empty.hpp> #include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/facilities/is_empty.hpp> #include <boost/preprocessor/facilities/is_empty.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp> #include <boost/preprocessor/variadic/to_seq.hpp>
#include <boost/preprocessor/seq/for_each.hpp> #include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/push_front.hpp> #include <boost/preprocessor/seq/push_front.hpp>
#define BOOST_FUSION_ADAPT_STRUCT_FILLER_0(X, Y) \ #define BOOST_FUSION_ADAPT_STRUCT_FILLER_0(X, Y) \
BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTE_FILLER(X,Y) \ BOOST_FUSION_ADAPT_STRUCT_WRAP_ATTR(X,Y) \
BOOST_FUSION_ADAPT_STRUCT_FILLER_1 BOOST_FUSION_ADAPT_STRUCT_FILLER_1
#define BOOST_FUSION_ADAPT_STRUCT_FILLER_1(X, Y) \ #define BOOST_FUSION_ADAPT_STRUCT_FILLER_1(X, Y) \
BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTE_FILLER(X,Y) \ BOOST_FUSION_ADAPT_STRUCT_WRAP_ATTR(X,Y) \
BOOST_FUSION_ADAPT_STRUCT_FILLER_0 BOOST_FUSION_ADAPT_STRUCT_FILLER_0
#define BOOST_FUSION_ADAPT_STRUCT_FILLER_0_END #define BOOST_FUSION_ADAPT_STRUCT_FILLER_0_END
#define BOOST_FUSION_ADAPT_STRUCT_FILLER_1_END #define BOOST_FUSION_ADAPT_STRUCT_FILLER_1_END
#define BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTE_FILLER(X, Y) \ #define BOOST_FUSION_ADAPT_STRUCT_WRAP_ATTR(X, Y) \
BOOST_PP_IF(BOOST_PP_IS_EMPTY(X), \ BOOST_PP_IF(BOOST_PP_IS_EMPTY(X), \
((1, (Y))), \ ((1, (Y))), \
((2, (X,Y))) \ ((2, (X,Y))) \
) )
#define BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR_SIZE(ATTRIBUTE) \
BOOST_PP_TUPLE_ELEM(2, 0, ATTRIBUTE)
#define BOOST_FUSION_ADAPT_STRUCT_WRAPPEDATTR(ATTRIBUTE) \
BOOST_PP_TUPLE_ELEM(2, 1, ATTRIBUTE)
#if BOOST_PP_VARIADICS #if BOOST_PP_VARIADICS
# define BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER_OP(r, data, elem) \ # define BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER_OP(r, unused, elem) \
BOOST_PP_IF(BOOST_FUSION_PP_IS_SEQ(elem), \ BOOST_PP_IF(BOOST_FUSION_PP_IS_SEQ(elem), \
BOOST_PP_CAT( BOOST_FUSION_ADAPT_STRUCT_FILLER_0 elem ,_END), \ BOOST_PP_CAT( BOOST_FUSION_ADAPT_STRUCT_FILLER_0 elem ,_END), \
BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTE_FILLER(BOOST_FUSION_ADAPT_AUTO, \ BOOST_FUSION_ADAPT_STRUCT_WRAP_ATTR(BOOST_FUSION_ADAPT_AUTO, \
elem) \ elem))
)
# define BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER(...) \ # define BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER(...) \
BOOST_PP_SEQ_PUSH_FRONT( \ BOOST_PP_SEQ_PUSH_FRONT( \
BOOST_PP_SEQ_FOR_EACH( \ BOOST_PP_SEQ_FOR_EACH( \
BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER_OP, \ BOOST_FUSION_ADAPT_STRUCT_ATTRIBUTES_FILLER_OP, \
unused, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), \ unused, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), \
(0,0) \ (0,0))
)
#endif // BOOST_PP_VARIADICS #endif // BOOST_PP_VARIADICS

View File

@ -30,6 +30,7 @@
#include <boost/fusion/mpl.hpp> #include <boost/fusion/mpl.hpp>
#include <boost/fusion/support/is_view.hpp> #include <boost/fusion/support/is_view.hpp>
#include <boost/mpl/front.hpp> #include <boost/mpl/front.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/is_sequence.hpp> #include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/assert.hpp> #include <boost/mpl/assert.hpp>
#include <boost/mpl/not.hpp> #include <boost/mpl/not.hpp>
@ -42,19 +43,33 @@ namespace ns
struct x_member; struct x_member;
struct y_member; struct y_member;
struct z_member; struct z_member;
struct non_member;
struct point struct point
{ {
int x; int x;
int y; int y;
int z;
}; };
} }
BOOST_FUSION_ADAPT_ASSOC_STRUCT( #if BOOST_PP_VARIADICS
ns::point, BOOST_FUSION_ADAPT_ASSOC_STRUCT(
(int, x, ns::x_member) ns::point,
(int, y, ns::y_member) (x, ns::x_member)
) (y, ns::y_member)
(int, z, ns::z_member)
)
#else // BOOST_PP_VARIADICS
BOOST_FUSION_ADAPT_ASSOC_STRUCT(
ns::point,
(BOOST_FUSION_ADAPT_AUTO, x, ns::x_member)
(BOOST_FUSION_ADAPT_AUTO, y, ns::y_member)
(int, z, ns::z_member)
)
#endif
int int
main() main()
@ -68,28 +83,30 @@ main()
{ {
BOOST_MPL_ASSERT_NOT((traits::is_view<ns::point>)); BOOST_MPL_ASSERT_NOT((traits::is_view<ns::point>));
ns::point p = {123, 456}; ns::point p = {123, 456, 789};
std::cout << at_c<0>(p) << std::endl; std::cout << at_c<0>(p) << std::endl;
std::cout << at_c<1>(p) << std::endl; std::cout << at_c<1>(p) << std::endl;
std::cout << at_c<2>(p) << std::endl;
std::cout << p << std::endl; std::cout << p << std::endl;
BOOST_TEST(p == make_vector(123, 456)); BOOST_TEST(p == make_vector(123, 456, 789));
at_c<0>(p) = 6; at_c<0>(p) = 6;
at_c<1>(p) = 9; at_c<1>(p) = 9;
BOOST_TEST(p == make_vector(6, 9)); at_c<2>(p) = 12;
BOOST_TEST(p == make_vector(6, 9, 12));
BOOST_STATIC_ASSERT(boost::fusion::result_of::size<ns::point>::value == 2); BOOST_STATIC_ASSERT(boost::fusion::result_of::size<ns::point>::value == 3);
BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty<ns::point>::value); BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty<ns::point>::value);
BOOST_TEST(front(p) == 6); BOOST_TEST(front(p) == 6);
BOOST_TEST(back(p) == 9); BOOST_TEST(back(p) == 12);
} }
{ {
fusion::vector<int, float> v1(4, 2); fusion::vector<int, float, int> v1(4, 2, 2);
ns::point v2 = {5, 3}; ns::point v2 = {5, 3, 3};
fusion::vector<long, double> v3(5, 4); fusion::vector<long, double, int> v3(5, 4, 4);
BOOST_TEST(v1 < v2); BOOST_TEST(v1 < v2);
BOOST_TEST(v1 <= v2); BOOST_TEST(v1 <= v2);
BOOST_TEST(v2 > v1); BOOST_TEST(v2 > v1);
@ -102,15 +119,15 @@ main()
{ {
// conversion from ns::point to vector // conversion from ns::point to vector
ns::point p = {5, 3}; ns::point p = {5, 3, 3};
fusion::vector<int, long> v(p); fusion::vector<int, long, int> v(p);
v = p; v = p;
} }
{ {
// conversion from ns::point to list // conversion from ns::point to list
ns::point p = {5, 3}; ns::point p = {5, 3, 3};
fusion::list<int, long> l(p); fusion::list<int, long, int> l(p);
l = p; l = p;
} }
@ -118,15 +135,18 @@ main()
// assoc stuff // assoc stuff
BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<ns::point, ns::x_member>)); BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<ns::point, ns::x_member>));
BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<ns::point, ns::y_member>)); BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<ns::point, ns::y_member>));
BOOST_MPL_ASSERT((mpl::not_<boost::fusion::result_of::has_key<ns::point, ns::z_member> >)); BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<ns::point, ns::z_member>));
BOOST_MPL_ASSERT((mpl::not_<boost::fusion::result_of::has_key<ns::point, ns::non_member> >));
BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<ns::point, ns::x_member>::type, int>)); BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<ns::point, ns::x_member>::type, int>));
BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<ns::point, ns::y_member>::type, int>)); BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<ns::point, ns::y_member>::type, int>));
BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<ns::point, ns::z_member>::type, int>));
ns::point p = {5, 3}; ns::point p = {5, 3, 9};
BOOST_TEST(at_key<ns::x_member>(p) == 5); BOOST_TEST(at_key<ns::x_member>(p) == 5);
BOOST_TEST(at_key<ns::y_member>(p) == 3); BOOST_TEST(at_key<ns::y_member>(p) == 3);
BOOST_TEST(at_key<ns::z_member>(p) == 9);
} }
{ {
@ -134,6 +154,9 @@ main()
BOOST_MPL_ASSERT((boost::is_same< BOOST_MPL_ASSERT((boost::is_same<
boost::fusion::result_of::value_at_c<ns::point,0>::type boost::fusion::result_of::value_at_c<ns::point,0>::type
, mpl::front<ns::point>::type>)); , mpl::front<ns::point>::type>));
BOOST_MPL_ASSERT((boost::is_same<
boost::fusion::result_of::value_at_c<ns::point,2>::type
, mpl::back<ns::point>::type>));
} }
return boost::report_errors(); return boost::report_errors();

View File

@ -39,27 +39,42 @@ namespace ns
struct y_member; struct y_member;
struct z_member; struct z_member;
template<typename X, typename Y> struct non_member;
template<typename X, typename Y, typename Z>
struct point struct point
{ {
X x; X x;
Y y; Y y;
Z z;
}; };
} }
BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT( #if BOOST_PP_VARIADICS
(X)(Y), BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT(
(ns::point)(X)(Y), (X)(Y)(Z),
(int, x, ns::x_member) (ns::point)(X)(Y)(Z),
(int, y, ns::y_member) (int, x, ns::x_member)
) (Y, y, ns::y_member)
(z, ns::z_member)
)
#else // BOOST_PP_VARIADICS
BOOST_FUSION_ADAPT_ASSOC_TPL_STRUCT(
(X)(Y)(Z),
(ns::point)(X)(Y)(Z),
(int, x, ns::x_member)
(Y, y, ns::y_member)
(BOOST_FUSION_ADAPT_AUTO, z, ns::z_member)
)
#endif
int int
main() main()
{ {
using namespace boost::fusion; using namespace boost::fusion;
typedef ns::point<int,int> point; typedef ns::point<int,int,float> point;
std::cout << tuple_open('['); std::cout << tuple_open('[');
std::cout << tuple_close(']'); std::cout << tuple_close(']');
@ -67,28 +82,30 @@ main()
{ {
BOOST_MPL_ASSERT_NOT((traits::is_view<point>)); BOOST_MPL_ASSERT_NOT((traits::is_view<point>));
point p = {123, 456}; point p = {123, 456, 789.43f};
std::cout << at_c<0>(p) << std::endl; std::cout << at_c<0>(p) << std::endl;
std::cout << at_c<1>(p) << std::endl; std::cout << at_c<1>(p) << std::endl;
std::cout << at_c<2>(p) << std::endl;
std::cout << p << std::endl; std::cout << p << std::endl;
BOOST_TEST(p == make_vector(123, 456)); BOOST_TEST(p == make_vector(123, 456, 789.43f));
at_c<0>(p) = 6; at_c<0>(p) = 6;
at_c<1>(p) = 9; at_c<1>(p) = 9;
BOOST_TEST(p == make_vector(6, 9)); at_c<2>(p) = 12;
BOOST_TEST(p == make_vector(6, 9, 12));
BOOST_STATIC_ASSERT(boost::fusion::result_of::size<point>::value == 2); BOOST_STATIC_ASSERT(boost::fusion::result_of::size<point>::value == 3);
BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty<point>::value); BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty<point>::value);
BOOST_TEST(front(p) == 6); BOOST_TEST(front(p) == 6);
BOOST_TEST(back(p) == 9); BOOST_TEST(back(p) == 12);
} }
{ {
vector<int, float> v1(4, 2); vector<int, float, int> v1(4, 2, 2);
point v2 = {5, 3}; point v2 = {5, 3, 3};
vector<long, double> v3(5, 4); vector<long, double, float> v3(5, 4, 4.13f);
BOOST_TEST(v1 < v2); BOOST_TEST(v1 < v2);
BOOST_TEST(v1 <= v2); BOOST_TEST(v1 <= v2);
BOOST_TEST(v2 > v1); BOOST_TEST(v2 > v1);
@ -101,15 +118,15 @@ main()
{ {
// conversion from point to vector // conversion from point to vector
point p = {5, 3}; point p = {5, 3, 3};
vector<int, long> v(p); vector<int, long, int> v(p);
v = p; v = p;
} }
{ {
// conversion from point to list // conversion from point to list
point p = {5, 3}; point p = {5, 3, 3};
list<int, long> l(p); list<int, long, int> l(p);
l = p; l = p;
} }
@ -117,15 +134,18 @@ main()
// assoc stuff // assoc stuff
BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<point, ns::x_member>)); BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<point, ns::x_member>));
BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<point, ns::y_member>)); BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<point, ns::y_member>));
BOOST_MPL_ASSERT((boost::mpl::not_<boost::fusion::result_of::has_key<point, ns::z_member> >)); BOOST_MPL_ASSERT((boost::fusion::result_of::has_key<point, ns::z_member>));
BOOST_MPL_ASSERT((boost::mpl::not_<boost::fusion::result_of::has_key<point, ns::non_member> >));
BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<point, ns::x_member>::type, int>)); BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<point, ns::x_member>::type, int>));
BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<point, ns::y_member>::type, int>)); BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<point, ns::y_member>::type, int>));
BOOST_MPL_ASSERT((boost::is_same<boost::fusion::result_of::value_at_key<point, ns::z_member>::type, float>));
point p = {5, 3}; point p = {5, 3, 9};
BOOST_TEST(at_key<ns::x_member>(p) == 5); BOOST_TEST(at_key<ns::x_member>(p) == 5);
BOOST_TEST(at_key<ns::y_member>(p) == 3); BOOST_TEST(at_key<ns::y_member>(p) == 3);
BOOST_TEST(at_key<ns::z_member>(p) == 9);
} }
return boost::report_errors(); return boost::report_errors();