CVR-Lib last update 20 Sep 2009

cvrMetaProgrammingTools.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005
00003  * Peter Doerfler
00004  *
00005  *
00006  * This file is part of the Computer Vision and Robotics Library (CVR-Lib)
00007  *
00008  * The CVR-Lib is free software; you can redistribute it and/or
00009  * modify it under the terms of the BSD License.
00010  *
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without
00014  * modification, are permitted provided that the following conditions are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright notice,
00017  *    this list of conditions and the following disclaimer.
00018  *
00019  * 2. Redistributions in binary form must reproduce the above copyright notice,
00020  *    this list of conditions and the following disclaimer in the documentation
00021  *    and/or other materials provided with the distribution.
00022  *
00023  * 3. Neither the name of the authors nor the names of its contributors may be
00024  *    used to endorse or promote products derived from this software without
00025  *    specific prior written permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00028  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00030  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00031  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00032  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00033  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00034  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00035  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00037  * POSSIBILITY OF SUCH DAMAGE.
00038  */
00039 
00040 
00041 
00042 /**
00043  * \file   cvrMetaProgrammingTools.h
00044  *         Contains some useful meta programming tools such as if_t, switch_t
00045  * \author Peter Doerfler
00046  * \date   23.09.2005
00047  *
00048  * $Id: cvrMetaProgrammingTools.h,v 1.4 2007/09/15 18:29:28 alvarado Exp $
00049  */
00050 
00051 #ifndef _CVR_META_PROGRAMMING_TOOLS_H_
00052 #define _CVR_META_PROGRAMMING_TOOLS_H_
00053 
00054 namespace cvr {
00055 
00056   /**
00057    * Namespace containing material intended for the internal use within the
00058    * CVR-Lib, but is not supposed to be used outside the library.
00059    */
00060   namespace internal {
00061 
00062     /**
00063      * are_same<T, U>::value is \a true if \c T \c == \c U and \a false
00064      * otherwise.
00065      */
00066     template <typename T, typename U>
00067     struct are_same {
00068       enum {value = false};
00069     };
00070 
00071     template <typename T>
00072     struct are_same<T, T> {
00073       enum {value = true};
00074     };
00075 
00076     /**
00077      * enable_if<T, bool b>::type is T if b is true and empty otherwise
00078      */
00079     template <typename T, bool b>
00080     struct enable_if {
00081     };
00082 
00083     template <typename T>
00084     struct enable_if<T, true> {
00085       typedef T type;
00086     };
00087 
00088 
00089     /**
00090      * Defines the if_t<B,THEN,ELSE>::type as THEN if B==true and as
00091      * ELSE if B==false.
00092      *
00093      * The following example is not from the real world but shows the idea:
00094      * \code
00095      * struct container<bool readOnly> {
00096      *   typedef typename internal::if_t<readOnly, const_iterator, iterator> iterator_type;
00097      *   iterator_type begin();
00098      * \endcode
00099      *
00100      */
00101     template <bool B, class THEN, class ELSE = void>
00102     struct if_t {
00103       typedef THEN type;
00104     };
00105 
00106     // specialization
00107     template <class THEN, class ELSE>
00108     struct if_t<false, THEN, ELSE> {
00109       typedef ELSE type;
00110     };
00111 
00112     // e.g if_t<false, T>::type no definitely creates a compilation error.
00113 //     template <class THEN>
00114 //     struct if_t<false, THEN, void> {
00115 //     };
00116 
00117     /**
00118      * Helper type for the cvr::internal::switch_t struct. Used as 'default'
00119      * when no default_t is given.
00120      */
00121     struct no_type {
00122       template <int>
00123       struct impl {
00124         typedef void type;
00125       };
00126     };
00127 
00128     /**
00129      * A "case" in a cvr::internal::switch_t. If the value used for switching
00130      * is equal to \p Y the switch_t returns \p T, otherwise it goes on with
00131      * the next \p CASE. Default for case is \p cvr::internal::no_type which
00132      * should be avoided.
00133      *
00134      * See cvr::internal::switch_t for a more detailed documentation.
00135      */
00136     template <int Y, class T, class CASE=no_type>
00137     struct case_t {
00138 
00139       template <int X>
00140       struct impl {
00141         typedef typename if_t<
00142           X==Y,
00143           T, typename CASE::template impl<X>::type
00144         >::type type;
00145       };
00146     };
00147 
00148     /**
00149      * Specifies the default type \p T in an cvr::internal::switch_t. See
00150      * there for further information.
00151      */
00152     template <class T>
00153     struct default_t {
00154       template <int>
00155       struct impl {
00156         typedef T type;
00157       };
00158     };
00159 
00160     /**
00161      * A compile time switch statement.
00162      *
00163      * It is recommended to use enum values or static const int
00164      * members for specifying \p X as well as the case parameters.
00165      *
00166      * The following examples clarify the syntax. They all use the
00167      * following setup, that defines a type foo<X>::type that is
00168      * dependent on the value of X:
00169      *
00170      * \code
00171      * enum VAL{One, Two, Three};
00172      * template <VAL X>
00173      * struct foo {
00174      *   typedef typename internal::switch_t<X, .....>::type type;
00175      * }
00176      * \endcode
00177      *
00178      * The most simple case is just a default type:
00179      * \code
00180      * typedef typename internal::switch_t<X,
00181      *   internal::default_t<int> >::type type;
00182      * \endcode
00183      *
00184      * Just one case could have been done using if_t as well, but like
00185      * this it is more easily extended. Here, if \c X == \c One then
00186      * \c type is \c float otherwise \c type is \c int.
00187      *
00188      * \code
00189      * typedef typename internal::switch_t<X,
00190      *   internal::case_t<One, float,
00191      *   internal::default_t<int> > >::type type;
00192      * \endcode
00193      *
00194      * Finally, and recommended, include all possible values as cases
00195      * in the enum and supply a default that will lead to a
00196      * notification of some sort. \b Note that it is considered bad style
00197      * not to provide a default.
00198      *
00199      * \code
00200      * typedef typename internal::switch_t<X,
00201      *   internal::case_t<One, int,
00202      *   internal::case_t<Two, float,
00203      *   internal::case_t<Three, std::complex<float>,
00204      *   internal::default_t<void> > > > >::type type;
00205      * \endcode
00206      */
00207     template <int X, class CASE>
00208     struct switch_t {
00209 
00210       typedef typename CASE::template impl<X>::type type;
00211     };
00212 
00213 
00214   } // namespace internal
00215 } // namespace cvr
00216 
00217 #endif

Generated on Sun Sep 20 22:08:00 2009 for CVR-Lib by Doxygen 1.5.8