Jeff Thompson | 86b6d64 | 2013-10-17 15:01:56 -0700 | [diff] [blame] | 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 | // NDNBOOST_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 NDNBOOST_SELECT_BY_SIZE_MAX_CASE 7 // (Needed when default was 2) |
| 27 | // #include <ndnboost/utility/select_by_size.hpp> |
| 28 | // |
| 29 | // using namespace ndnboost::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 | // NDNBOOST_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 | // NDNBOOST_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 NDNBOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED |
| 62 | #define NDNBOOST_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 <ndnboost/config.hpp> // NDNBOOST_STATIC_CONSTANT. |
| 69 | #include <ndnboost/preprocessor/cat.hpp> |
| 70 | #include <ndnboost/preprocessor/iteration/local.hpp> |
| 71 | |
| 72 | /* Alternative implementation using max_align. |
| 73 | |
| 74 | #include <ndnboost/type_traits/alignment_of.hpp> |
| 75 | #include <ndnboost/type_traits/type_with_alignment.hpp> |
| 76 | |
| 77 | namespace ndnboost { 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 | NDNBOOST_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 ndnboost { 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 ndnboost { namespace iostreams { namespace detail { \ |
| 113 | static const int NDNBOOST_PP_CAT(sizeof_case_, n) = sizeof(case_<n - 1>); \ |
| 114 | template<> \ |
| 115 | struct select_by_size< NDNBOOST_PP_CAT(sizeof_case_, n) > { \ |
| 116 | struct type { NDNBOOST_STATIC_CONSTANT(int, value = n - 1); }; \ |
| 117 | NDNBOOST_STATIC_CONSTANT(int, value = type::value); \ |
| 118 | }; \ |
| 119 | } } } \ |
| 120 | /**/ |
| 121 | |
| 122 | //--------------Default specializations of select_by_size---------------------// |
| 123 | |
| 124 | #define NDNBOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) |
| 125 | #define NDNBOOST_PP_LOCAL_LIMITS (0, 20) |
| 126 | #include NDNBOOST_PP_LOCAL_ITERATE() |
| 127 | #undef NDNBOOST_PP_LOCAL_MACRO |
| 128 | |
| 129 | //--------------Definition of SELECT_BY_SIZE----------------------------------// |
| 130 | |
| 131 | #define NDNBOOST_SELECT_BY_SIZE(type_, name, expr) \ |
| 132 | NDNBOOST_STATIC_CONSTANT( \ |
| 133 | unsigned, \ |
| 134 | NDNBOOST_PP_CAT(boost_select_by_size_temp_, name) = sizeof(expr) \ |
| 135 | ); \ |
| 136 | NDNBOOST_STATIC_CONSTANT( \ |
| 137 | type_, \ |
| 138 | name = \ |
| 139 | ( ::ndnboost::iostreams::detail::select_by_size< \ |
| 140 | NDNBOOST_PP_CAT(boost_select_by_size_temp_, name) \ |
| 141 | >::value ) \ |
| 142 | ) \ |
| 143 | /**/ |
| 144 | |
| 145 | #endif // #ifndef NDNBOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED |
| 146 | |
| 147 | //----------Specializations of SELECT_BY_SIZE (outside main inclued guards)---// |
| 148 | |
| 149 | #if defined(NDNBOOST_SELECT_BY_SIZE_MAX_CASE) && \ |
| 150 | NDNBOOST_SELECT_BY_SIZE_MAX_CASE > SELECT_BY_SIZE_MAX_SPECIALIZED |
| 151 | |
| 152 | #define NDNBOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) |
| 153 | #define NDNBOOST_PP_LOCAL_LIMITS \ |
| 154 | (SELECT_BY_SIZE_MAX_SPECIALIZED, NDNBOOST_SELECT_BY_SIZE_MAX_CASE) \ |
| 155 | /**/ |
| 156 | #include NDNBOOST_PP_LOCAL_ITERATE() |
| 157 | #undef NDNBOOST_PP_LOCAL_MACRO |
| 158 | #undef SELECT_BY_SIZE_MAX_SPECIALIZED |
| 159 | #define SELECT_BY_SIZE_MAX_SPECIALIZED NDNBOOST_SELECT_BY_SIZE_MAX_CASE |
| 160 | |
| 161 | #endif |