Select By Size

Author:Jonathan Turkanis
Contact:turkanis@kangaroologic.com
Date:2004-02-11
Copyright:Copyright Jonathan Turkanis 2004. All rights reserved

Contents

1. Overview
2. Usage
3. Rationale
4. Synopsis
5. Dependencies
6. Portability

Overview

The header <boost/utility/select_by_size.hpp> provides template classes and macros for determining the results of overload resolution at compile time using sizeof. It is intended as an alternative to type_traits::yes_type and type_traits::no_type from the Type Traits library. It provides an arbitrary number of types, case_<0>, case_<1>, case_<2>, ... , for use as the return types of helper functions, plus a template select_by_size which provides access to the result of the overload resolution. There is also a macro BOOST_SELECT_BY_SIZE, similar to BOOST_STATIC_CONSTANT, for use with compilers which have trouble with integral constant expressions. (See Coding Guidelines for Integral Constant Expressions.) For convenience, a single return type representing a negative value is also provided: case_<-1>.

All types decribes in this document reside in the namespace boost::utility.

The template case_

The defining property of the class template case_ is that the sizes of the types

    case_<-1>, case_<0>, case_<1>, case_<2>, case_<3>, ...
form a strictly increasing sequence. With well-behaved implementations, sizeof(case_<-1>) will be small, as will be the difference in size between adjacent types in the sequence.

The typedefs yes_type and no_type are provided as shorthands for case_<1> and case_<0>. Naturally, case_<true> and case_<false> may also be used.

The template select_by_size

The defining property of the class template select_by_size is that for each integer N in the range select_by_size through BOOST_SELECT_BY_SIZE_MAX_CASE, we have the equality

    select_by_size< sizeof(case_<N>) >::value == N

The macro BOOST_SELECT_BY_SIZE_MAX_CASE

In order to make use of select_by_size with specializations case_<N> for N other than -1, 0 and 1, the symbol BOOST_SELECT_BY_SIZE_MAX_CASE must be defined as an intergral value greater than or equal to N before including the header <boost/utility/select_by_size.hpp>. The header may be included multiple times with different values of BOOST_SELECT_BY_SIZE_MAX_CASE.

The macro BOOST_SELECT_BY_SIZE

The macro BOOST_SELECT_BY_SIZE(type, name, expr) can be used similarly to BOOST_STATIC_CONSTANT to define a static const intergral class member name of type type with value equal to select_by_size< sizeof(expr) >::value.

Usage

    #include <boost/static_assert.hpp>
    #define BOOST_SELECT_BY_SIZE_MAX_CASE 7  
    #include <boost/utility/select_by_size.hpp>

    using namespace boost::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("hello")) >::value;
        BOOST_STATIC_ASSERT(value == 7);
    };

    struct test2 {
        BOOST_SELECT_BY_SIZE(int, value, helper("hello"));
        BOOST_STATIC_ASSERT(value == 7);
    };

Rationale

The utility of type_traits::yes_type and type_traits::no_type is well-known. The advantages of using select_by_size are:

Until recently the author was aware of only one use for item (3). Thus he regarded the use of select_by_size with more than two cases as a trick. He then discovered a second use, elevating it to a method. With the discovery of a third use, it is now a programming paradigm. The three known uses are determing template arity, as in <boost/mpl/aux_/template_arity.hpp>, Joel de Guzman's type deduction system in the Boost Sandbox at <boost/utility/type_deduction.hpp>, and Reece Dunn's type deduction system for his Output Formatters library, also in the Boost Sandbox, at <boost/outfmt/detail/type_traits.hpp>.

Synopsis

    namespace boost {
      namespace utility {

        template<int N> struct case_;

        template<unsigned N> 
        struct select_by_size {
            struct type { 
                static const unsigned value = 
                    [M such that sizeof(case_<M>) == N];
            };
            static const unsigned value = type::value;
        };
 
        #define BOOST_SELECT_BY_SIZE(type, name, expr) [implementation-defined]
      } 
    }

Dependencies

The header <boost/utility/select_by_size.hpp> depends on Boost.Config and Boost.Preprocessor.

Portability

The program <libs/utility/select_by_size_test.cpp> has been tested successfully with the following compilers:


© Copyright Jonathan Turkanis 2004. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.