]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) |
2 | // (C) Copyright 2004-2007 Jonathan Turkanis | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) | |
5 | ||
6 | // See http://www.boost.org/libs/iostreams for documentation. | |
7 | ||
8 | // | |
9 | // Intended as an alternative to type_traits::yes_type and type_traits::no_type. | |
10 | // Provides an arbitrary number of types (case_<0>, case_<1>, ...) for | |
11 | // determining the results of overload resultion using 'sizeof', plus a uniform | |
12 | // means of using the result. yes_type and no_type are typedefs for case_<1> | |
13 | // and case_<0>. A single case with negative argument, case_<-1>, is also | |
14 | // provided, for convenience. | |
15 | // | |
16 | // This header may be included any number of times, with | |
17 | // BOOST_SELECT_BY_SIZE_MAX_CASE defined to be the largest N such that case_<N> | |
18 | // is needed for a particular application. It defaults to 20. | |
19 | // | |
20 | // This header depends only on Boost.Config and Boost.Preprocessor. Dependence | |
21 | // on Type Traits or MPL was intentionally avoided, to leave open the | |
22 | // possibility that select_by_size could be used by these libraries. | |
23 | // | |
24 | // Example usage: | |
25 | // | |
26 | // #define BOOST_SELECT_BY_SIZE_MAX_CASE 7 // (Needed when default was 2) | |
27 | // #include <boost/utility/select_by_size.hpp> | |
28 | // | |
29 | // using namespace boost::utility; | |
30 | // | |
31 | // case_<0> helper(bool); | |
32 | // case_<1> helper(int); | |
33 | // case_<2> helper(unsigned); | |
34 | // case_<3> helper(long); | |
35 | // case_<4> helper(unsigned long); | |
36 | // case_<5> helper(float); | |
37 | // case_<6> helper(double); | |
38 | // case_<7> helper(const char*); | |
39 | // | |
40 | // struct test { | |
41 | // static const int value = | |
42 | // select_by_size< sizeof(helper(9876UL)) >::value; | |
43 | // BOOST_STATIC_ASSERT(value == 4); | |
44 | // }; | |
45 | // | |
46 | // For compilers with integral constant expression problems, e.g. Borland 5.x, | |
47 | // one can also write | |
48 | // | |
49 | // struct test { | |
50 | // BOOST_SELECT_BY_SIZE(int, value, helper(9876UL)); | |
51 | // }; | |
52 | // | |
53 | // to define a static integral constant 'value' equal to | |
54 | // | |
55 | // select_by_size< sizeof(helper(9876UL)) >::value. | |
56 | // | |
57 | ||
58 | // Include guards surround all contents of this header except for explicit | |
59 | // specializations of select_by_size for case_<N> with N > 2. | |
60 | ||
61 | #ifndef BOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED | |
62 | #define BOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED | |
63 | ||
64 | // The lowest N for which select_by_size< sizeof(case_<N>) > has not been | |
65 | // specialized. | |
66 | #define SELECT_BY_SIZE_MAX_SPECIALIZED 20 | |
67 | ||
68 | #include <boost/config.hpp> // BOOST_STATIC_CONSTANT. | |
69 | #include <boost/preprocessor/cat.hpp> | |
70 | #include <boost/preprocessor/iteration/local.hpp> | |
71 | ||
72 | /* Alternative implementation using max_align. | |
73 | ||
74 | #include <boost/type_traits/alignment_of.hpp> | |
75 | #include <boost/type_traits/type_with_alignment.hpp> | |
76 | ||
77 | namespace boost { namespace utility { | |
78 | ||
79 | template<int N> | |
80 | struct case_ { char c[(N + 1) * alignment_of<detail::max_align>::value]; }; | |
81 | ||
82 | template<unsigned Size> | |
83 | struct select_by_size { | |
84 | BOOST_STATIC_CONSTANT(int, value = | |
85 | (Size / alignment_of<detail::max_align>::value - 1)); | |
86 | }; | |
87 | ||
88 | } } // End namespaces utility, boost. | |
89 | ||
90 | */ // End alternate implementation. | |
91 | ||
92 | namespace boost { namespace iostreams { namespace detail { | |
93 | ||
94 | //--------------Definition of case_-------------------------------------------// | |
95 | ||
96 | template<int N> struct case_ { char c1; case_<N - 1> c2; }; | |
97 | template<> struct case_<-1> { char c; }; | |
98 | typedef case_<true> yes_type; | |
99 | typedef case_<false> no_type; | |
100 | ||
101 | //--------------Declaration of select_by_size---------------------------------// | |
102 | ||
103 | template<unsigned Size> struct select_by_size; | |
104 | ||
105 | } } } // End namespaces detail, iostreams, boost. | |
106 | ||
107 | //--------------Definition of SELECT_BY_SIZE_SPEC-----------------------------// | |
108 | ||
109 | // Sepecializes select_by_size for sizeof(case<n-1>). The decrement is used | |
110 | // here because the preprocessor library doesn't handle negative integers. | |
111 | #define SELECT_BY_SIZE_SPEC(n) \ | |
112 | namespace boost { namespace iostreams { namespace detail { \ | |
113 | static const int BOOST_PP_CAT(sizeof_case_, n) = sizeof(case_<n - 1>); \ | |
114 | template<> \ | |
115 | struct select_by_size< BOOST_PP_CAT(sizeof_case_, n) > { \ | |
116 | struct type { BOOST_STATIC_CONSTANT(int, value = n - 1); }; \ | |
117 | BOOST_STATIC_CONSTANT(int, value = type::value); \ | |
118 | }; \ | |
119 | } } } \ | |
120 | /**/ | |
121 | ||
122 | //--------------Default specializations of select_by_size---------------------// | |
123 | ||
124 | #define BOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) | |
125 | #define BOOST_PP_LOCAL_LIMITS (0, 20) | |
126 | #include BOOST_PP_LOCAL_ITERATE() | |
127 | #undef BOOST_PP_LOCAL_MACRO | |
128 | ||
129 | //--------------Definition of SELECT_BY_SIZE----------------------------------// | |
130 | ||
131 | #define BOOST_SELECT_BY_SIZE(type_, name, expr) \ | |
132 | BOOST_STATIC_CONSTANT( \ | |
133 | unsigned, \ | |
134 | BOOST_PP_CAT(boost_select_by_size_temp_, name) = sizeof(expr) \ | |
135 | ); \ | |
136 | BOOST_STATIC_CONSTANT( \ | |
137 | type_, \ | |
138 | name = \ | |
139 | ( ::boost::iostreams::detail::select_by_size< \ | |
140 | BOOST_PP_CAT(boost_select_by_size_temp_, name) \ | |
141 | >::value ) \ | |
142 | ) \ | |
143 | /**/ | |
144 | ||
145 | #endif // #ifndef BOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED | |
146 | ||
147 | //----------Specializations of SELECT_BY_SIZE (outside main inclued guards)---// | |
148 | ||
149 | #if defined(BOOST_SELECT_BY_SIZE_MAX_CASE) && \ | |
150 | BOOST_SELECT_BY_SIZE_MAX_CASE > SELECT_BY_SIZE_MAX_SPECIALIZED | |
151 | ||
152 | #define BOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) | |
153 | #define BOOST_PP_LOCAL_LIMITS \ | |
154 | (SELECT_BY_SIZE_MAX_SPECIALIZED, BOOST_SELECT_BY_SIZE_MAX_CASE) \ | |
155 | /**/ | |
156 | #include BOOST_PP_LOCAL_ITERATE() | |
157 | #undef BOOST_PP_LOCAL_MACRO | |
158 | #undef SELECT_BY_SIZE_MAX_SPECIALIZED | |
159 | #define SELECT_BY_SIZE_MAX_SPECIALIZED BOOST_SELECT_BY_SIZE_MAX_CASE | |
160 | ||
161 | #endif |