| // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) |
| // (C) Copyright 2004-2007 Jonathan Turkanis |
| // 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.) |
| |
| // See http://www.boost.org/libs/iostreams for documentation. |
| |
| // |
| // Intended as an alternative to type_traits::yes_type and type_traits::no_type. |
| // Provides an arbitrary number of types (case_<0>, case_<1>, ...) for |
| // determining the results of overload resultion using 'sizeof', plus a uniform |
| // means of using the result. yes_type and no_type are typedefs for case_<1> |
| // and case_<0>. A single case with negative argument, case_<-1>, is also |
| // provided, for convenience. |
| // |
| // This header may be included any number of times, with |
| // NDNBOOST_SELECT_BY_SIZE_MAX_CASE defined to be the largest N such that case_<N> |
| // is needed for a particular application. It defaults to 20. |
| // |
| // This header depends only on Boost.Config and Boost.Preprocessor. Dependence |
| // on Type Traits or MPL was intentionally avoided, to leave open the |
| // possibility that select_by_size could be used by these libraries. |
| // |
| // Example usage: |
| // |
| // #define NDNBOOST_SELECT_BY_SIZE_MAX_CASE 7 // (Needed when default was 2) |
| // #include <ndnboost/utility/select_by_size.hpp> |
| // |
| // using namespace ndnboost::utility; |
| // |
| // case_<0> helper(bool); |
| // case_<1> helper(int); |
| // case_<2> helper(unsigned); |
| // case_<3> helper(long); |
| // case_<4> helper(unsigned long); |
| // case_<5> helper(float); |
| // case_<6> helper(double); |
| // case_<7> helper(const char*); |
| // |
| // struct test { |
| // static const int value = |
| // select_by_size< sizeof(helper(9876UL)) >::value; |
| // NDNBOOST_STATIC_ASSERT(value == 4); |
| // }; |
| // |
| // For compilers with integral constant expression problems, e.g. Borland 5.x, |
| // one can also write |
| // |
| // struct test { |
| // NDNBOOST_SELECT_BY_SIZE(int, value, helper(9876UL)); |
| // }; |
| // |
| // to define a static integral constant 'value' equal to |
| // |
| // select_by_size< sizeof(helper(9876UL)) >::value. |
| // |
| |
| // Include guards surround all contents of this header except for explicit |
| // specializations of select_by_size for case_<N> with N > 2. |
| |
| #ifndef NDNBOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED |
| #define NDNBOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED |
| |
| // The lowest N for which select_by_size< sizeof(case_<N>) > has not been |
| // specialized. |
| #define SELECT_BY_SIZE_MAX_SPECIALIZED 20 |
| |
| #include <ndnboost/config.hpp> // NDNBOOST_STATIC_CONSTANT. |
| #include <ndnboost/preprocessor/cat.hpp> |
| #include <ndnboost/preprocessor/iteration/local.hpp> |
| |
| /* Alternative implementation using max_align. |
| |
| #include <ndnboost/type_traits/alignment_of.hpp> |
| #include <ndnboost/type_traits/type_with_alignment.hpp> |
| |
| namespace ndnboost { namespace utility { |
| |
| template<int N> |
| struct case_ { char c[(N + 1) * alignment_of<detail::max_align>::value]; }; |
| |
| template<unsigned Size> |
| struct select_by_size { |
| NDNBOOST_STATIC_CONSTANT(int, value = |
| (Size / alignment_of<detail::max_align>::value - 1)); |
| }; |
| |
| } } // End namespaces utility, boost. |
| |
| */ // End alternate implementation. |
| |
| namespace ndnboost { namespace iostreams { namespace detail { |
| |
| //--------------Definition of case_-------------------------------------------// |
| |
| template<int N> struct case_ { char c1; case_<N - 1> c2; }; |
| template<> struct case_<-1> { char c; }; |
| typedef case_<true> yes_type; |
| typedef case_<false> no_type; |
| |
| //--------------Declaration of select_by_size---------------------------------// |
| |
| template<unsigned Size> struct select_by_size; |
| |
| } } } // End namespaces detail, iostreams, boost. |
| |
| //--------------Definition of SELECT_BY_SIZE_SPEC-----------------------------// |
| |
| // Sepecializes select_by_size for sizeof(case<n-1>). The decrement is used |
| // here because the preprocessor library doesn't handle negative integers. |
| #define SELECT_BY_SIZE_SPEC(n) \ |
| namespace ndnboost { namespace iostreams { namespace detail { \ |
| static const int NDNBOOST_PP_CAT(sizeof_case_, n) = sizeof(case_<n - 1>); \ |
| template<> \ |
| struct select_by_size< NDNBOOST_PP_CAT(sizeof_case_, n) > { \ |
| struct type { NDNBOOST_STATIC_CONSTANT(int, value = n - 1); }; \ |
| NDNBOOST_STATIC_CONSTANT(int, value = type::value); \ |
| }; \ |
| } } } \ |
| /**/ |
| |
| //--------------Default specializations of select_by_size---------------------// |
| |
| #define NDNBOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) |
| #define NDNBOOST_PP_LOCAL_LIMITS (0, 20) |
| #include NDNBOOST_PP_LOCAL_ITERATE() |
| #undef NDNBOOST_PP_LOCAL_MACRO |
| |
| //--------------Definition of SELECT_BY_SIZE----------------------------------// |
| |
| #define NDNBOOST_SELECT_BY_SIZE(type_, name, expr) \ |
| NDNBOOST_STATIC_CONSTANT( \ |
| unsigned, \ |
| NDNBOOST_PP_CAT(boost_select_by_size_temp_, name) = sizeof(expr) \ |
| ); \ |
| NDNBOOST_STATIC_CONSTANT( \ |
| type_, \ |
| name = \ |
| ( ::ndnboost::iostreams::detail::select_by_size< \ |
| NDNBOOST_PP_CAT(boost_select_by_size_temp_, name) \ |
| >::value ) \ |
| ) \ |
| /**/ |
| |
| #endif // #ifndef NDNBOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED |
| |
| //----------Specializations of SELECT_BY_SIZE (outside main inclued guards)---// |
| |
| #if defined(NDNBOOST_SELECT_BY_SIZE_MAX_CASE) && \ |
| NDNBOOST_SELECT_BY_SIZE_MAX_CASE > SELECT_BY_SIZE_MAX_SPECIALIZED |
| |
| #define NDNBOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) |
| #define NDNBOOST_PP_LOCAL_LIMITS \ |
| (SELECT_BY_SIZE_MAX_SPECIALIZED, NDNBOOST_SELECT_BY_SIZE_MAX_CASE) \ |
| /**/ |
| #include NDNBOOST_PP_LOCAL_ITERATE() |
| #undef NDNBOOST_PP_LOCAL_MACRO |
| #undef SELECT_BY_SIZE_MAX_SPECIALIZED |
| #define SELECT_BY_SIZE_MAX_SPECIALIZED NDNBOOST_SELECT_BY_SIZE_MAX_CASE |
| |
| #endif |