diff --git a/include/aggregate.hpp b/include/aggregate.hpp index 32d0e56..0648090 100644 --- a/include/aggregate.hpp +++ b/include/aggregate.hpp @@ -15,27 +15,73 @@ struct compo_t { using alignment_t = size_t; template < typename T > -struct has_trv { - template < typename U > static auto check(U u) -> decltype(u.trv(), std::true_type{}) { } +struct has_alignof { + template < typename U > static auto check(U u) -> decltype(U::alignof_(), std::true_type{}); + static std::false_type check(...); + static bool const value = decltype(check(std::declval()))::value; +}; + +template < typename T > +constexpr auto alignof_() -> std::enable_if_t< has_alignof< T >::value, alignment_t > +{ + return T::alignof_(); +} + +template < typename T > +constexpr auto alignof_() -> std::enable_if_t< !has_alignof< T >::value, alignment_t > +{ + return alignof(T); +} + +template < typename T> +struct has_align { + template < typename U > static auto check(U u) -> decltype(U::align_mode, std::true_type{}); static std::false_type check(...); -public: static bool const value = decltype(check(std::declval()))::value; }; +template < alignment_t A, typename T> +constexpr auto decision_align() -> std::enable_if_t< has_align::value, alignment_t > { return T::alignof_(); } + +template < alignment_t A, typename T> +constexpr auto decision_align() -> std::enable_if_t< !has_align::value, alignment_t > { return A; } + template < alignment_t Align, typename T > constexpr size_t align(size_t o) { size_t a = Align; if (Align == 0) /* natural align */ - a = sizeof(T); + a = alignof_(); + size_t m = (a-1); + return (o & m) ? ((o + (a-1)) & ~m) : o; +} + +template < alignment_t Align > +constexpr size_t align(size_t o) +{ + size_t a = Align; + if (Align == 0) /* natural align */ + return o; size_t m = (a-1); return (o & m) ? ((o + (a-1)) & ~m) : o; } + +template < typename T > +struct has_trv { + template < typename U > static auto check(U u) -> decltype(u.trv(), std::true_type{}) { } + static std::false_type check(...); + static bool const value = decltype(check(std::declval()))::value; +}; + /* trv ������. trv �̓e���v���[�g������ align �����‚���. (�e���v���[�g�����̓f�t�H���g�� alignment �����‚ׂ�) */ -template < typename T, alignment_t Align = 1 > constexpr auto sizeof_() -> decltype(T::trv()) { return T::template trv< Align >(); } +template < typename T, alignment_t Align = 1 > +constexpr auto sizeof_() -> std::enable_if_t< has_trv::value, size_t > +{ + return T::template trv< Align >(); +} /* trv �������Ȃ� */ template < typename T, alignment_t Align = 1 > @@ -43,72 +89,127 @@ constexpr auto sizeof_() -> std::enable_if_t< !has_trv::value, size_t > { return align(sizeof(T)); } + +template < typename T, alignment_t A > +struct has_placement { + template < typename U > static auto check(U u) -> decltype(U::template placement(), std::true_type{}) { } + static std::false_type check(...); + static bool const value = decltype(check(std::declval()))::value; +}; + +/* placement ���l������ size �v�Z���Ăяo��. */ +template < typename T, alignment_t Align = 1 > +constexpr auto sizeof_(size_t place) -> std::enable_if_t< has_placement::value, size_t > +{ + return T::template placement< Align >(place); +} + +template < typename T, alignment_t Align = 1 > +constexpr auto sizeof_(size_t) -> std::enable_if_t< !has_placement::value, size_t > +{ + return align(sizeof(T)); +} + +/* C++14 �� std::max �� constexpr �ł��ł����͂�����, clang-3.5+libc++ �łȂ������� */ +template < typename CAR, typename... CDR > +constexpr CAR constexpr_max(CAR&& car, CDR&&... cdr){ + CAR r = car; + using s = std::initializer_list; + (void)s{ (void(r = r < cdr ? cdr : r),0)... }; + return r; +} template < alignment_t Align, size_t Acc, typename ...Ts > struct sigma_size { static const size_t value = Acc; }; -template < alignment_t Align, size_t Acc, typename CAR> -struct sigma_size< Align, Acc, CAR > { - static const size_t value = align< Align, CAR >(Acc + sizeof_< CAR >()); -}; - template < alignment_t Align, size_t Acc, typename CAR, typename ...CDR> struct sigma_size< Align, Acc, CAR, CDR... > { - static const size_t value = sigma_size< Align, align< Align, CAR >(Acc + sizeof_< CAR >()), CDR... >::value; + static const alignment_t a_ = decision_align< Align, CAR >(); + static const size_t value = sigma_size< Align, align< a_, CAR >(Acc + sizeof_< CAR, a_ >(Acc)), CDR... >::value; }; -template < alignment_t Align, typename ...Ts > +template < alignment_t Align, size_t Acc, typename ...Ts > +constexpr size_t sigma_type_list(type_list< Ts ... >&&) +{ + return sigma_size< Align, Acc, Ts... >::value; +} + +template < alignment_t Align, size_t Acc, typename Cur, typename ...Ts > constexpr size_t sigma_type_list(type_list< Ts ... >&&) { - return sigma_size< Align, 0, Ts... >::value; + return sigma_size< Align, Acc, Cur, Ts... >::value; } /* offset �v�Z�̃T�u�֐�: �^ T �� offset() �������Ă���� Rest... �̃p�^�[���ɏ]���ĒT����, �Ȃ���ΏI�[����. */ -template < alignment_t Align, typename T, size_t...Pos > -constexpr auto offset_() -> decltype(T::template offset< Align, Pos... >::value) +template < alignment_t Align, size_t Acc, typename T, size_t...Pos > +constexpr auto offset_() -> decltype(T::template offset< Align, Acc, Pos... >::value) { - return T::template offset< Align, Pos... >::value; + return T::template offset< Align, Acc, Pos... >::value ; } -template < typename T, size_t... Pos > +template < typename T, alignment_t A, size_t Acc, size_t... Pos > struct has_offset { - template < typename U > static auto check(U u) -> decltype(U::template offset< 0, Pos ... >::value, std::true_type{}) { } + template < typename U > static auto check(U u) -> decltype(U::template offset< A, Acc, Pos ... >::value, std::true_type{}) { } static std::false_type check(...); public: static bool const value = decltype(check(std::declval()))::value; }; /* offset �������Ȃ��̂� Pos... �̒T���͏I�� */ -template < alignment_t Align, typename T, size_t...Pos > -constexpr auto offset_() -> std::enable_if_t< !has_offset::value, size_t > +template < alignment_t Align, size_t Acc, typename T, size_t...Pos > +constexpr auto offset_() -> std::enable_if_t< !has_offset::value, size_t > { - return std::is_empty< T >::value ? T() : sizeof(T); + return Acc + (std::is_empty< T >::value ? 0 : sizeof(T)); } - + /* aggregation */ template < typename ...S > struct agg_t : public compo_t { template < alignment_t Align = 1 > - constexpr static size_t trv() + constexpr static size_t trv(size_t placement=0) { return sigma_size< Align, 0, S... >::value; } - template < alignment_t Align, size_t... Rest > struct offset { static const size_t value = 0; }; + template < alignment_t Align = 1 > + static constexpr size_t placement(size_t place = 0) + { + return trv(place); + } + + template < alignment_t Align, size_t Acc, size_t... Rest > struct offset { static const size_t value = Acc; }; /* offset �� Idx-1 �܂ł̃T�C�Y�̑��a����, address alignment ����̕ۏ؂̂��߂� Idx �� type ��m��K�v������. - �v�Z�̓r��������𖞂����K�v������. */ - template < alignment_t Align, size_t Cur > - struct offset< Align, Cur > { static const size_t value = align< Align, typename at_type< Cur, S...>::type >(sigma_type_list< Align >(typename to_types< Cur, S... >::types{})); }; - - template < alignment_t Align, size_t Cur, size_t ... Rest > - struct offset< Align, Cur, Rest...> { - static const size_t value = sigma_type_list< Align >(typename to_types< Cur, S... >::types{}) + - offset_< Align, typename at_type< Cur, S... >::type, Rest... >(); + �v�Z�̓r��������𖞂����K�v������. + ���̂Ƃ��� alignment �� placement alignment ��, �^�̗v�� alignment �ɗD�悷��. + (alignment ���I�[�o�[���C�h�����Ƃ�, ������ type_t �� align ��� placement-align ���D�悳���. + ������ type_t �̓����� type_t �� align ���K�p�����. ���� padding/headroom �� type_t ������. + headroom �� type_t �����ڎ��e���� agg_t/sel_t �� offset ���Ƃ�Όv�Z�ς݂ƂȂ�) + using T = type_t< agg_t< char, type_t< agg_t< int >, 0 >, 1 > �̂Ƃ�: + get< T, 0, 1 >::offset �� placement-alignment=1 �ɏ]�� 1 + get< T, 0, 1, 0>::offset �� T �̓��� alignment �ɏ]�� 4 + get< T, 0, 1, 0, 0>::offset �͓����� alignment �ɏ]�� 4 + */ +#if 1 + template < alignment_t Align, size_t Acc, size_t Cur > + struct offset< Align, Acc, Cur > { + /* �ŏI column �� ���a. �Ō�̗v�f�̉��Z�O�̒l��Ԃ� */ + using T_ = typename at_type< Cur, S...>::type; + static const size_t value = align< Align, T_ >(sigma_type_list< Align, Acc >(typename to_types< Cur, S... >::types{})); + }; +#endif + + template < alignment_t Align, size_t Acc, size_t Cur, size_t ... Rest > + struct offset< Align, Acc, Cur, Rest...> { + using T_ = typename at_type< Cur, S...>::type; + /* column ���Ƃ̑��a: */ + static const size_t s = align< Align, T_ >(sigma_type_list< Align, Acc >(typename to_types< Cur, S... >::types{})); + + static const size_t value = align< Align, T_ >(offset_< Align, s, T_, Rest... >()); }; template < alignment_t Align, size_t... Rest > struct get { using type = void; }; @@ -118,31 +219,32 @@ struct agg_t : public compo_t { using type = typename at_type< Pos, S... >::type::template get< Align, Rest ... >::type; }; + static constexpr alignment_t alignof_() + { + return constexpr_max(typu::alignof_()...); + } }; -/* C++14 �� std::max �� constexpr �ł��ł����͂�����, clang-3.5+libc++ �łȂ������� */ -template < typename CAR, typename... CDR > -constexpr CAR constexpr_max(CAR&& car, CDR&&... cdr){ - CAR r = car; - using s = std::initializer_list; - (void)s{ (void(r = r < cdr ? cdr : r),0)... }; - return r; -} - /* selector */ template < typename ...S > struct sel_t : public compo_t { template < alignment_t Align = 1 > - constexpr static size_t trv() + constexpr static size_t trv(size_t placement=0) { return constexpr_max(sizeof_()...); } - template < alignment_t Align, size_t... Rest > struct offset { static const size_t value = 0; }; - template < alignment_t Align, size_t Pos > struct offset< Align, Pos > { static const size_t value = 0; }; - template < alignment_t Align, size_t Pos, size_t ... Rest > - struct offset< Align, Pos, Rest...> { - static const size_t value = offset_< Align, typename at_type< Pos, S... >::type, Rest... >(); + template < alignment_t Align = 1 > + constexpr static size_t placement(size_t place=0) + { + return trv(place); + } + + template < alignment_t Align, size_t Acc, size_t... Rest > struct offset { static const size_t value = Acc; }; + //template < alignment_t Align, size_t Acc, size_t Pos > struct offset< Align, Acc, Pos > { static const size_t value = Acc; }; + template < alignment_t Align, size_t Acc, size_t Pos, size_t ... Rest > + struct offset< Align, Acc, Pos, Rest...> { + static const size_t value = offset_< Align, Acc, typename at_type< Pos, S... >::type, Rest... >(); }; template < alignment_t Align, size_t... Rest > struct get { using type = void; }; @@ -151,13 +253,17 @@ struct sel_t : public compo_t { struct get< Align, Pos, Rest...> { using type = typename at_type< Pos, S... >::type::template get< Align, Rest ... >::type; }; - + + static constexpr alignment_t alignof_() + { + return constexpr_max(typu::alignof_()...); + } }; template < typename T, T ...S > struct sel_t_t { template < alignment_t A=1 > - constexpr static size_t trv() + constexpr static size_t trv(size_t placement=0) { return constexpr_max(S...); } @@ -177,28 +283,92 @@ template < typename S, alignment_t Align, typename Enabled = void > struct type_t { }; +/* ���e����邷�ׂĂ̌^�͌ŗL�̃A���C�������g������, type_t �͂�����I�[�o�[���C�h����. + type_t �͑��� type_t �Ɏ��e�����Ƃ�, ���� type_t �̃A���C�������g�ɃI�[�o�[���C�h�����. + + �����, ��� type_t �����R���p�N�g�ȃA���C����v������Ƃ��ɗv���ɖ�����������. + using T1 = type_t< agg_t< double >, 0 >; + using T0 = type_t< char, T2, 1>; + �Ƃ����, T0 �̎��e�^�� packed �ƂȂ� T1 �� offset=1 �ƂȂ邪, + T1 �̎��e�^�͎��R�� align ��v�������̂� type_t �� 7byte �� headroom �ƂȂ� + T1 ���e�^�̃I�t�Z�b�g�� 8byte align �ƂȂ�. +*/ template < typename S, alignment_t Align> struct type_t < S, Align, std::enable_if_t< std::is_base_of< compo_t, S >::value > > { using sub = S; - static const size_t align = Align; + static const alignment_t align_mode = Align; /* maybe 0 */ + static const size_t align = align_mode ? align_mode : sub::alignof_(); /* a concret value. non zero */ + + template < alignment_t A > + static constexpr size_t align_(size_t o) + { + static_assert(A != 0, "align_ needs not align-mode"); + size_t a = A; + size_t m = (a-1); + return (o & m) ? ((o + m) & ~m): o; + } - template < alignment_t A = Align > - constexpr static size_t trv() + /* type_t ���l�X�g���� alignment �� override ����Ƃ�, + type_t �̔z�u�I�t�Z�b�g�ɂ���� type_t ���g�� pack ���܂މ”\�������� */ + template < alignment_t EA = Align > + constexpr static size_t trv(size_t place = 0) { - return sizeof_(); + if (EA == Align) + return sizeof_(); + /* ���g�� align �� Enclosure �� align ���قȂ�ꍇ, + ���g�� align �� sizeof_ ���v�Z��, placement �������� offset �� enclosure �� align �Ōv�Z����. + */ + size_t size = sizeof_(); + return align_< EA ? EA : align >(place) - place + size; } + /* type_t ���l�X�g���� alignment �� override ����Ƃ�, + type_t �̔z�u�I�t�Z�b�g�ɂ���� type_t ���g�� pack ���܂މ”\�������� */ + template < alignment_t EA = Align > + constexpr static size_t placement(size_t place = 0) + { + if (EA == Align) + return sizeof_(place); + /* ���g�� align �� Enclosure �� align ���قȂ�ꍇ, + ���g�� align �� sizeof_ ���v�Z��, placement �������� offset �� enclosure �� align �Ōv�Z����. + */ + size_t size = sizeof_(place); + return align_< EA ? EA : align >(place) - place + size; + } + + /* ignore the first 0 */ template < size_t Cur, size_t ...Rest > - constexpr static size_t offset() + constexpr static size_t offset_from() { - return sub::template offset< Align, Rest... >::value; + static_assert(Cur == 0, "type_t has to get 0 for the first enclosure"); + return sub::template offset< Align, 0, Rest... >::value; } + + template < alignment_t A, size_t offs > + constexpr static size_t check_aligned() + { + static_assert((offs & ((A==0 ? sub::alignof_() : A) - 1)) == 0, "offset is not aligned"); + return offs; + } + + template < alignment_t A, size_t Acc, size_t Pos, size_t ... Rest > + struct offset { + /* type_t �̓��� offset �̌v�Z�ɂ����Ă΂�Ȃ��̂ŏ�� placement align �͖��� */ + static const size_t value = align_< align >(offset_< align, Acc, sub, Rest... >()); + }; + template < alignment_t A, size_t... Rest > struct get { using type = void; }; + template < alignment_t A, size_t Pos > struct get< A, Pos > { using type = sub; }; + template < alignment_t A, size_t Pos, size_t ... Rest > + struct get< A, Pos, Rest...> { + using type = typename sub::template get< Align, Rest ... >::type; + }; + /* get �C���^�[�t�F�C�X�̂��߂� compo_t �̔h���Ƃ�����, type_t ���g�� compo_t ���p�����Ȃ�. �܂� variadic parameter ���Ƃ�Ȃ�����, get< type_t<...>, 0 > �Ƃ���� sub �ɃA�N�Z�X���邽�߂ɂ̓g���b�N���K�v�ɂȂ���. �Ƃ肠�������ꉻ�Ō떂����. - (���������ŏ��̎����͂����v��Ȃ��̂ł͂Ȃ����Ƃ����C������) */ + (���������ŏ��̎����͂����v��Ȃ��̂ł͂Ȃ����Ƃ����C�����邪 type_t �� alignment override �̍ۋ��E�ƂȂ�) */ template < size_t ... Pos > struct inner; template < size_t Cur, size_t ...Rest > struct inner< Cur, Rest... > { @@ -208,6 +378,8 @@ struct type_t < S, Align, std::enable_if_t< std::is_base_of< compo_t, S >::value struct inner { using type = sub; }; + + static constexpr alignment_t alignof_() { return align; } }; /* get ���J�C���^�[�t�F�C�X. @@ -218,8 +390,8 @@ struct type_t < S, Align, std::enable_if_t< std::is_base_of< compo_t, S >::value template < typename T, size_t... Pos > struct get { using type = typename T::template inner< Pos... >::type; - static const size_t size = sizeof_(); - static const size_t offset = T::template offset(); + static const size_t size = sizeof_(); + static const size_t offset = T::template offset_from(); }; } diff --git a/test/recurse.cpp b/test/recurse.cpp index aefee7c..1a17053 100644 --- a/test/recurse.cpp +++ b/test/recurse.cpp @@ -1,16 +1,10 @@ #include #include -template < typename C, typename...P > -size_t foo(C c, P... p) -{ - return c; -} - int main() { using namespace typu; - + printf("%s\n", typeid(agg_t< int, int >::get< 0 >::type).name()); printf("%zu\n", type_t< agg_t< int >, 1 >::trv()); @@ -27,57 +21,58 @@ int main() using Simple1 = type_t< agg_t< char, char, int, double >, 1 >; printf("sizeof Simple1: %zu (14)\n", Simple1::trv()); - printf("char1: %zu (0)\n", Simple1::offset<0, 0>()); - printf("char2: %zu (1)\n", Simple1::offset<0, 1>()); - printf("int: %zu (2)\n", Simple1::offset<0, 2>()); - printf("double: %zu (6)\n", Simple1::offset<0, 3>()); + printf("char1: %zu (0)\n", Simple1::offset_from<0, 0>()); + printf("char2: %zu (1)\n", Simple1::offset_from<0, 1>()); + printf("int: %zu (2)\n", Simple1::offset_from<0, 2>()); + printf("double: %zu (6)\n", Simple1::offset_from<0, 3>()); using Sel1 = type_t< sel_t< int, char, bool, double >, 1 >; printf("sizeof Sel1: %zu (8)\n", Sel1::trv()); - printf("int: %zu (0)\n", Sel1::offset<0, 0>()); - printf("char: %zu (0)\n", Sel1::offset<0, 1>()); - printf("bool: %zu (0)\n", Sel1::offset<0, 2>()); - printf("double: %zu (0)\n", Sel1::offset<0, 3>()); - - using Agg1 = type_t< agg_t< int, float, agg_t< double, float > >, 1 >; - printf("sizeof Agg1: %zu (20)\n", Agg1::trv()); - printf("agg0: %zu (0)\n", Agg1::offset<0>()); - printf("agg0:int: %zu (0)\n", Agg1::offset<0, 0>()); - printf("agg0:float: %zu (4)\n", Agg1::offset<0, 1>()); - printf("agg1: %zu (8)\n", Agg1::offset<0, 2>()); - printf("agg1:double %zu (8)\n", Agg1::offset<0, 2, 0>()); - printf("agg1:float %zu (16)\n", Agg1::offset<0, 2, 1>()); + printf("int: %zu (0)\n", Sel1::offset_from<0, 0>()); + printf("char: %zu (0)\n", Sel1::offset_from<0, 1>()); + printf("bool: %zu (0)\n", Sel1::offset_from<0, 2>()); + printf("double: %zu (0)\n", Sel1::offset_from<0, 3>()); + + using Agg1 = type_t< agg_t< int, float, agg_t< double, float >, char >, 1 >; + printf("sizeof Agg1: %zu (21)\n", Agg1::trv()); + printf("agg0: %zu (0)\n", Agg1::offset_from<0>()); + printf("agg0:int: %zu (0)\n", Agg1::offset_from<0, 0>()); + printf("agg0:float: %zu (4)\n", Agg1::offset_from<0, 1>()); + printf("agg1: %zu (8)\n", Agg1::offset_from<0, 2>()); + printf("agg1:double %zu (8)\n", Agg1::offset_from<0, 2, 0>()); + printf("agg1:float %zu (16)\n", Agg1::offset_from<0, 2, 1>()); + printf("agg0:char %zu (20)\n", Agg1::offset_from<0, 3>()); using Sel2 = type_t< sel_t< int, float, sel_t< double, float > >, 1 >; printf("sizeof Sel2: %zu (8)\n", Sel2::trv()); - printf("sel0: %zu (0)\n", Sel2::offset<0>()); - printf("sel0:int: %zu (0)\n", Sel2::offset<0, 0>()); - printf("sel0:float: %zu (0)\n", Sel2::offset<0, 1>()); - printf("sel1: %zu (0)\n", Sel2::offset<0, 2>()); - printf("sel1:double %zu (0)\n", Sel2::offset<0, 2, 0>()); - printf("sel1:float %zu (0)\n", Sel2::offset<0, 2, 1>()); + printf("sel0: %zu (0)\n", Sel2::offset_from<0>()); + printf("sel0:int: %zu (0)\n", Sel2::offset_from<0, 0>()); + printf("sel0:float: %zu (0)\n", Sel2::offset_from<0, 1>()); + printf("sel1: %zu (0)\n", Sel2::offset_from<0, 2>()); + printf("sel1:double %zu (0)\n", Sel2::offset_from<0, 2, 0>()); + printf("sel1:float %zu (0)\n", Sel2::offset_from<0, 2, 1>()); using SA1 = type_t< sel_t< int, float, agg_t< double, float > >, 1 >; printf("sizeof SA1: %zu (12)\n", SA1::trv()); - printf("sel0: %zu (0)\n", SA1::offset<0>()); - printf("sel0:int: %zu (0)\n", SA1::offset<0, 0>()); - printf("sel0:float: %zu (0)\n", SA1::offset<0, 1>()); - printf("agg0: %zu (0)\n", SA1::offset<0, 2>()); - printf("agg0:double %zu (0)\n", SA1::offset<0, 2, 0>()); - printf("agg0:float %zu (8)\n", SA1::offset<0, 2, 1>()); + printf("sel0: %zu (0)\n", SA1::offset_from<0>()); + printf("sel0:int: %zu (0)\n", SA1::offset_from<0, 0>()); + printf("sel0:float: %zu (0)\n", SA1::offset_from<0, 1>()); + printf("agg0: %zu (0)\n", SA1::offset_from<0, 2>()); + printf("agg0:double %zu (0)\n", SA1::offset_from<0, 2, 0>()); + printf("agg0:float %zu (8)\n", SA1::offset_from<0, 2, 1>()); using AS1 = type_t< agg_t< int, float, sel_t< double, float > >, 1 >; printf("sizeof AS1: %zu (16)\n", AS1::trv()); - printf("agg0: %zu (0)\n", AS1::offset<0>()); - printf("agg0:int: %zu (0)\n", AS1::offset<0, 0>()); - printf("agg0:float: %zu (4)\n", AS1::offset<0, 1>()); - printf("sel0: %zu (8)\n", AS1::offset<0, 2>()); - printf("sel0:double %zu (8)\n", AS1::offset<0, 2, 0>()); - printf("sel0:float %zu (8)\n", AS1::offset<0, 2, 1>()); + printf("agg0: %zu (0)\n", AS1::offset_from<0>()); + printf("agg0:int: %zu (0)\n", AS1::offset_from<0, 0>()); + printf("agg0:float: %zu (4)\n", AS1::offset_from<0, 1>()); + printf("sel0: %zu (8)\n", AS1::offset_from<0, 2>()); + printf("sel0:double %zu (8)\n", AS1::offset_from<0, 2, 0>()); + printf("sel0:float %zu (8)\n", AS1::offset_from<0, 2, 1>()); - printf("bool: %zu (0)\n", Sel1::offset<0, 2>()); - printf("double: %zu (0)\n", Sel1::offset<0, 3>()); + printf("bool: %zu (0)\n", Sel1::offset_from<0, 2>()); + printf("double: %zu (0)\n", Sel1::offset_from<0, 3>()); using T = type_t< agg_t< char, sel_t< int, char > , sel_t< agg_t< int, int >, agg_t< double, double > >, sel_t< int > >, 0 >; printf("%zu\n", T::trv()); @@ -91,11 +86,11 @@ int main() printf("offset: %zu\n", sel_t< int, sel_t< int, int > >::offset< 1, 1 >::value); #if 1 - printf("%zu (5)\n", T::offset<0, 2>()); - printf("%zu (5)\n", T::offset<0, 2, 1>()); /* sel> �̂ق�����, sel �̊J�n�܂ł� offset �Ȃ̂� 5 */ - printf("%zu(13)\n", T::offset<0, 2, 1, 1>()); /* sel> �̓�–ڂ� double �܂ł� offset �Ȃ̂� 13 */ - printf("%zu (5)\n", T::offset<0, 2, 0>()); /* sel> �œ��� */ - printf("%zu(21)\n", T::offset<0, 3>()); /* sel>,agg> �̎��Ȃ̂� 21 */ + printf("%zu (5)\n", T::offset_from<0, 2>()); + printf("%zu (5)\n", T::offset_from<0, 2, 1>()); /* sel> �̂ق�����, sel �̊J�n�܂ł� offset �Ȃ̂� 5 */ + printf("%zu(13)\n", T::offset_from<0, 2, 1, 1>()); /* sel> �̓�–ڂ� double �܂ł� offset �Ȃ̂� 13 */ + printf("%zu (5)\n", T::offset_from<0, 2, 0>()); /* sel> �œ��� */ + printf("%zu(21)\n", T::offset_from<0, 3>()); /* sel>,agg> �̎��Ȃ̂� 21 */ #endif printf("%s \n", typeid(get< T, 0, 2, 1>::type).name()); @@ -132,5 +127,113 @@ int main() printf("offset(align:0): %zu (16)\n", get< Aligned0_3, 0, 3>::offset); printf("offset(align:0): %zu (17)\n", get< Aligned0_3, 0, 4>::offset); printf("offset(align:0): %zu (20)\n", get< Aligned0_3, 0, 5>::offset); + + using Sub = agg_t< char, char, char >; + using Sub2 = agg_t< char, Sub, char >; + using Aligned0_4 = type_t< agg_t< char, char, char, Sub, Sub, Sub2, int, char >, 0 >; + printf("size(align:0): %zu (21)\n", get< Aligned0_4, 0 >::size); + printf("offset: %zu (0) <0,0>\n", get< Aligned0_4, 0, 0>::offset); + printf("offset: %zu (1) <0,1>\n", get< Aligned0_4, 0, 1>::offset); + printf("offset: %zu (2) <0,2>\n", get< Aligned0_4, 0, 2>::offset); + printf("offset: %zu (3) <0,3>\n", get< Aligned0_4, 0, 3>::offset); + printf("offset: %zu (3) <0,3,0>\n", get< Aligned0_4, 0, 3, 0>::offset); + printf("offset: %zu (4) <0,3,1>\n", get< Aligned0_4, 0, 3, 1>::offset); + printf("offset: %zu (5) <0,3,2>\n", get< Aligned0_4, 0, 3, 2>::offset); + printf("offset: %zu (6) <0,4,0>\n", get< Aligned0_4, 0, 4, 0>::offset); + printf("offset: %zu (7) <0,4,1>\n", get< Aligned0_4, 0, 4, 1>::offset); + printf("offset: %zu (8) <0,4,2>\n", get< Aligned0_4, 0, 4, 2>::offset); + printf("offset: %zu (9) <0,5,0>\n", get< Aligned0_4, 0, 5, 0>::offset); + printf("offset: %zu (10) <0,5,1>\n", get< Aligned0_4, 0, 5, 1>::offset); + printf("offset: %zu (10) <0,5,1,0>\n", get< Aligned0_4, 0, 5, 1, 0>::offset); + printf("offset: %zu (11) <0,5,1,1>\n", get< Aligned0_4, 0, 5, 1, 1>::offset); + printf("offset: %zu (12) <0,5,1,2>\n", get< Aligned0_4, 0, 5, 1, 2>::offset); + printf("offset: %zu (13)<0,5,2>\n", get< Aligned0_4, 0, 5, 2>::offset); + printf("offset: %zu (16)<0,6>\n", get< Aligned0_4, 0, 6>::offset); + printf("offset: %zu (20)<0,7>\n", get< Aligned0_4, 0, 7>::offset); + + using T0 = type_t< agg_t< char, type_t< agg_t< int >, 0> >, 1 >; + printf("offset: %zu <0,1> (1) align:1\n", get< T0, 0, 1 >::offset); + printf("offset: %zu <0,1,0> (4) align:1->0\n", get< T0, 0, 1, 0 >::offset); + printf("offset: %zu <0,1,0,0>(4) align:0\n", get< T0, 0, 1, 0, 0 >::offset); + + using SubT = type_t < agg_t< char, char, char >, 0 >; + using SubT2 = type_t < agg_t< char, SubT, char >, 0 >; + using Aligned0_5 = type_t< agg_t< char, char, char, SubT, SubT, SubT2, int, char >, 0 >; + printf("size(align:0): %zu (21)\n", get< Aligned0_5, 0 >::size); + printf("offset: %zu (0) <0,0>\n", get< Aligned0_5, 0, 0>::offset); + printf("offset: %zu (1) <0,1>\n", get< Aligned0_5, 0, 1>::offset); + printf("offset: %zu (2) <0,2>\n", get< Aligned0_5, 0, 2>::offset); + printf("offset: %zu (3) <0,3>\n", get< Aligned0_5, 0, 3>::offset); + printf("offset: %zu (3) <0,3,0,0>\n", get< Aligned0_5, 0, 3, 0, 0>::offset); + printf("offset: %zu (4) <0,3,0,1>\n", get< Aligned0_5, 0, 3, 0, 1>::offset); + printf("offset: %zu (5) <0,3,0,2>\n", get< Aligned0_5, 0, 3, 0, 2>::offset); + printf("offset: %zu (6) <0,4,0,0>\n", get< Aligned0_5, 0, 4, 0, 0>::offset); + printf("offset: %zu (7) <0,4,0,1>\n", get< Aligned0_5, 0, 4, 0, 1>::offset); + printf("offset: %zu (8) <0,4,0,2>\n", get< Aligned0_5, 0, 4, 0, 2>::offset); + printf("offset: %zu (9) <0,5,0,0>\n", get< Aligned0_5, 0, 5, 0, 0>::offset); + printf("offset: %zu (10) <0,5,0,1>\n", get< Aligned0_5, 0, 5, 0, 1>::offset); + printf("offset: %zu (10) <0,5,0,1,0,0>\n", get< Aligned0_5, 0, 5, 0, 1, 0, 0>::offset); + printf("offset: %zu (11) <0,5,0,1,0,1>\n", get< Aligned0_5, 0, 5, 0, 1, 0, 1>::offset); + printf("offset: %zu (12) <0,5,0,1,0,2>\n", get< Aligned0_5, 0, 5, 0, 1, 0, 2>::offset); + printf("offset: %zu (13)<0,5,2>\n", get< Aligned0_5, 0, 5, 0, 2>::offset); + printf("offset: %zu (16)<0,6>\n", get< Aligned0_5, 0, 6>::offset); + printf("offset: %zu (20)<0,7>\n", get< Aligned0_5, 0, 7>::offset); + + // alighment override + using Aligned_1_0 = type_t< agg_t< char, int, type_t< agg_t, 0>, char, char, char >, 1>; + /* 0 1 5 8 F + |-+----+---+--------| + +0 |1| 4|pad| 8| + type_t^ ^agg_t + +10 |1|1|1| + */ + printf("size(align:-): %zu (19)\n", get< Aligned_1_0, 0 >::size); + printf("offset<0,0>(align:1): %zu (0)\n", get< Aligned_1_0, 0, 0>::offset); + printf("offset<0,1>(align:1): %zu (1)\n", get< Aligned_1_0, 0, 1>::offset); + /* align=0 �� type_t �͏�� enclosure �� placement align �ɏ]�� */ + printf("offset<0,2>(align:0): %zu (5)\n", get< Aligned_1_0, 0, 2>::offset); + printf("size: %zu (8)\n", get< Aligned_1_0, 0, 2>::size); +#if 0 + printf("size: %zu (8) placement-align:1 type_t-align:%zu real-align:%zu\n", get< Aligned_1_0, 0, 2>::type::placement<1>(5), + get< Aligned_1_0, 0, 2>::type::align, + alignof_< get< Aligned_1_0, 0, 2, 0>::type >()); +#endif + /* agg_t �� alignment �� type_t �ɏ]�� */ + printf("offset<0,2,0>(align:0): %zu (8)\n", get< Aligned_1_0, 0, 2, 0>::offset); + printf("offset<0,2,0,0>(align:0): %zu (8)\n", get< Aligned_1_0, 0, 2, 0, 0>::offset); + //printf("align (align:0): %zu (8)\n", get< Aligned_1_0, 0, 2>::type::alignof_()); // debug + printf("offset<0,3>(align:1): %zu (16)\n", get< Aligned_1_0, 0, 3>::offset); + printf("offset<0,4>(align:1): %zu (17)\n", get< Aligned_1_0, 0, 4>::offset); + printf("offset<0,5>(align:1): %zu (18)\n", get< Aligned_1_0, 0, 5>::offset); + + /* �O��,����� padding ������(�ǂ���� type_t �̊O�� padding ������) */ + using Aligned_0_1 = type_t< agg_t< char, int, char, type_t< agg_t, 2>, int, char, char >, 0>; + /* 0 4 8 |A F + |-+--+----+-+-+------| + +0 |1|pa| 4|1|p| 6/8| + ^type_t/agg_t(align=2) + 2/8|pa| 4|1|1| + +10 |--+--+----+-+-+ + 0 |2 |4 |8|9| + ~^ ^int + */ + printf("size(align:-): %zu (26)\n", get< Aligned_0_1, 0 >::size); + printf("offset<0,0>(align:0): %zu (0)\n", get< Aligned_0_1, 0, 0>::offset); + printf("offset<0,1>(align:0): %zu (4)\n", get< Aligned_0_1, 0, 1>::offset); + printf("offset<0,2>(align:0): %zu (8)\n", get< Aligned_0_1, 0, 2>::offset); + printf("offset<0,3>(align:1): %zu (10)\n", get< Aligned_0_1, 0, 3>::offset); + printf("size (align:1): %zu (8)\n", get< Aligned_0_1, 0, 3>::size); + printf("offset(align:1): %zu (10)\n", get< Aligned_0_1, 0, 3, 0, 0>::offset); + printf("type_t align<0,3> (align:0): %zu (2)\n", get< Aligned_0_1, 0, 3>::type::alignof_()); // debug + printf("real align<0,3> (align:0): %zu (8)\n", typu::alignof_< get< Aligned_0_1, 0, 3>::type::sub >()); // debug + printf("size (align:1): %zu (8)\n", get< Aligned_0_1, 0, 3>::type::trv<1>(10)); // debug + printf("size (align:0): %zu (8)\n", get< Aligned_0_1, 0, 3>::size); // debug + printf("size (align:0): %zu (8) padded\n", get< Aligned_0_1, 0, 3>::type::placement<0>(10)); // debug + printf("offset<0,4>(align:0): %zu (20)\n", get< Aligned_0_1, 0, 4>::offset); + //printf("align (align:0): %zu (4)\n", Aligned_0_1::alignof_()); // debug + printf("offset<0,5>(align:0): %zu (24)\n", get< Aligned_0_1, 0, 5>::offset); + printf("offset<0,6>(align:0): %zu (25)\n", get< Aligned_0_1, 0, 6>::offset); + + //printf("align (align:0): %zu (20) padded\n", get< Aligned_0_1, 0, 4>::type::trv<0>(20)); // debug return 0; }