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 162