/
type_size.hpp
164 lines (143 loc) · 4.83 KB
/
type_size.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright (c) 2012 Vinay C Amatya
// Copyright (c) 2007-2012 Hartmut Kaiser
//
// 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)
#if !defined(HPX_giMcvwgb6F6ljtAzZHfS99KSE6gn3KnvWt1TgTfV)
#define HPX_giMcvwgb6F6ljtAzZHfS99KSE6gn3KnvWt1TgTfV
#include <hpx/hpx_fwd.hpp>
#include <hpx/traits.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/fusion/include/accumulate.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
namespace hpx { namespace traits
{
//////////////////////////////////////////////////////////////////////////
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(uses_sizeof);
}
template <typename T, typename Enable>
struct type_size
{
typedef void uses_sizeof;
// flags are used for serialization options which may affect final encoded size
static BOOST_FORCEINLINE std::size_t call(T const&, int)
{
return sizeof(T);
}
};
// handle references
template <typename T>
struct type_size<T&>
: type_size<T>
{};
template <typename T>
struct type_size<T&&>
: type_size<T>
{};
///////////////////////////////////////////////////////////////////////////
// handle containers
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator)
BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
template <typename T>
struct is_container
: boost::mpl::bool_<
has_value_type<T>::value && has_iterator<T>::value &&
has_size_type<T>::value && has_reference<T>::value>
{};
template <typename T>
struct is_container<T&>
: is_container<T>
{};
}
template <typename T>
struct type_size<T,
typename boost::enable_if<traits::detail::is_container<T> >::type>
{
template <typename T_>
static BOOST_FORCEINLINE
std::size_t call(T_ const& v, int flags, boost::mpl::false_)
{
std::size_t sum = sizeof(T_);
typename T_::const_iterator end = v.end();
for (typename T_::const_iterator it = v.begin(); it != end; ++it)
sum += type_size<typename T_::value_type>::call(*it, flags);
return sum;
}
template <typename T_>
static BOOST_FORCEINLINE
std::size_t call(T_ const& v, int, boost::mpl::true_)
{
return sizeof(T_) + v.size() * sizeof(typename T_::value_type); //-V119
}
static BOOST_FORCEINLINE std::size_t call(T const& v, int flags)
{
typedef boost::mpl::bool_<
traits::detail::has_uses_sizeof<
traits::type_size<typename T::value_type>
>::value> predicate;
return call(v, flags, predicate());
}
};
//////////////////////////////////////////////////////////////////////////
// handle Fusion sequences
namespace detail
{
struct get_size
{
typedef std::size_t result_type;
template <typename T>
BOOST_FORCEINLINE std::size_t
operator()(std::size_t size, T const& t, int flags) const
{
return size + type_size<T>::call(t, flags);
}
};
}
template <typename T>
struct type_size<T,
typename boost::enable_if<boost::fusion::traits::is_sequence<T> >::type>
{
static BOOST_FORCEINLINE std::size_t call(T const& v, int flags)
{
std::size_t sum = sizeof(T);
return boost::fusion::accumulate(v, sum,
util::bind(traits::detail::get_size(),
util::placeholders::_1, util::placeholders::_2, flags));
}
};
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct type_size<boost::shared_ptr<T> >
{
static BOOST_FORCEINLINE
std::size_t call(boost::shared_ptr<T> const& p, int flags)
{
return type_size<T>::call(*p, flags);
}
};
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct type_size<boost::intrusive_ptr<T> >
{
static BOOST_FORCEINLINE
std::size_t call(boost::intrusive_ptr<T> const& p, int flags)
{
return type_size<T>::call(*p, flags);
}
};
//////////////////////////////////////////////////////////////////////////
template <typename T>
BOOST_FORCEINLINE std::size_t get_type_size(T const& t, int flags)
{
return type_size<T>::call(t, flags);
}
}}
#endif