last update 20 Sep 2009 |
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