1 // ========================================================================== 2 // SeqAn - The Library for Sequence Analysis 3 // ========================================================================== 4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above copyright 13 // notice, this list of conditions and the following disclaimer in the 14 // documentation and/or other materials provided with the distribution. 15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of 16 // its contributors may be used to endorse or promote products derived 17 // from this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE 23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 // DAMAGE. 30 // 31 // ========================================================================== 32 // Author: Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de> 33 // ========================================================================== 34 // "enable if" functionality. 35 // ========================================================================== 36 37 // SEQAN_NO_GENERATED_FORWARDS 38 39 // TODO(holtgrew): Rename *2 Metafunctions to *C metafunctions. 40 // TODO(holtgrew): Document properly. 41 42 #ifndef SEQAN_INCLUDE_SEQAN_BASIC_METAPROGRAMMING_ENABLE_IF_H_ 43 #define SEQAN_INCLUDE_SEQAN_BASIC_METAPROGRAMMING_ENABLE_IF_H_ 44 45 namespace seqan { 46 47 // ============================================================================ 48 // Forwards 49 // ============================================================================ 50 51 // ============================================================================ 52 // Tags, Classes, Enums 53 // ============================================================================ 54 55 // ============================================================================ 56 // Metafunctions 57 // ============================================================================ 58 59 /*! 60 * @defgroup EnableIfFunctionality Enable-If Functionality 61 * @brief The metafunctions and macros for enabling/disabling of functions. 62 * 63 * The <tt>EnableIf</tt> metafunctions also support the shortcut to <tt>::Type</tt> members as described for the @link 64 * LogicMetaprogramming logical metaprogramming metafunctions @endlink. 65 * 66 * <b>Enable-if is an advanced technique and mostly interesting if you want to extend the SeqAn library with generic 67 * algorithms. The average developer does not have to know about this technique.</b>. 68 * 69 * @see LogicalValuesTags 70 * @see LogicMetaprogramming 71 */ 72 73 // ---------------------------------------------------------------------------- 74 // Metafunction EnableIf 75 // ---------------------------------------------------------------------------- 76 77 /*! 78 * @mfn EnableIfFunctionality#EnableIf 79 * @headerfile <seqan/basic.h> 80 * @brief Metafunction to use for conditionally enabling code. 81 * 82 * @signature EnableIf<TBool, T = void>::Type 83 * 84 * @tparam TBool The Tag <tt>True</tt> or <tt>False</tt> to use for enabling/disabling. 85 * @tparam T Dummy, do not set. 86 * 87 * @return Type Set to <tt>T</tt>. Only defined if <tt>TBool</tt> is <tt>True</tt>. This triggers the SFINAE behaviour 88 * in C++ which can be used to enable/disable functions. 89 * 90 * Do not use directly but use through the enable if/disable if macros. 91 * 92 * @see EnableIfFunctionality#SEQAN_FUNC_ENABLE_IF 93 * @see EnableIfFunctionality#SEQAN_FUNC_DISABLE_IF 94 * @see EnableIfFunctionality#SEQAN_CTOR_ENABLE_IF 95 * @see EnableIfFunctionality#SEQAN_CTOR_DISABLE_IF 96 */ 97 98 template <typename TBool, typename T = void> 99 struct EnableIf : EnableIf<typename TBool::Type, T> {}; 100 101 template <typename T> 102 struct EnableIf<False, T> {}; 103 104 template <typename T> 105 struct EnableIf<True, T> 106 { 107 typedef T Type; 108 }; 109 110 //template <typename T> 111 //struct EnableIf<False, T> {}; 112 113 // ---------------------------------------------------------------------------- 114 // Metafunction DisableIf 115 // ---------------------------------------------------------------------------- 116 117 /*! 118 * @mfn EnableIfFunctionality#DisableIf 119 * @headerfile <seqan/basic.h> 120 * @brief Metafunction to use for conditionally disabling code. 121 * 122 * @signature DisableIf<TBool, T = void>::Type 123 * 124 * @tparam TBool The Tag <tt>True</tt> or <tt>False</tt> to use for enabling/disabling. 125 * @tparam T Dummy, do not set. 126 * 127 * @return Type Set to <tt>T</tt>. Only defined if <tt>TBool</tt> is <tt>False</tt>. This triggers the SFINAE behaviour 128 * in C++ which can be used to enable/disable functions. 129 * 130 * Do not use directly but use through the enable if/disable if macros. 131 * 132 * @see EnableIfFunctionality#SEQAN_FUNC_ENABLE_IF 133 * @see EnableIfFunctionality#SEQAN_FUNC_DISABLE_IF 134 * @see EnableIfFunctionality#SEQAN_CTOR_ENABLE_IF 135 * @see EnableIfFunctionality#SEQAN_CTOR_DISABLE_IF 136 */ 137 138 template <typename TBool, typename T = void> 139 struct DisableIf : DisableIf<typename TBool::Type, T> {}; 140 141 template <typename T> 142 struct DisableIf<True, T> {}; 143 144 template <typename T> 145 struct DisableIf<False, T> 146 { 147 typedef T Type; 148 }; 149 150 // ---------------------------------------------------------------------------- 151 // Metafunction EnableIf2 152 // ---------------------------------------------------------------------------- 153 154 /*! 155 * @mfn EnableIfFunctionality#EnableIf2 156 * @headerfile <seqan/basic.h> 157 * @deprecated Will be renamed to EnableIfC. 158 * @brief Metafunction to use for conditionally enabling code, bool version. 159 * 160 * @signature EnableIf2<BOOL, T = void>::Type 161 * 162 * @tparam BOOL The <tt>bool</tt> constant to evaluate for enabling/disabling. 163 * @tparam T Dummy, do not set. 164 * 165 * @return Type Set to <tt>T</tt>. Only defined if <tt>BOOL</tt> is <tt>true</tt>. This triggers the SFINAE behaviour 166 * in C++ which can be used to enable/disable functions. 167 * 168 * Do not use directly but use through the enable if/disable if macros. 169 * 170 * @see EnableIfFunctionality#SEQAN_FUNC_ENABLE_IF 171 * @see EnableIfFunctionality#SEQAN_FUNC_DISABLE_IF 172 * @see EnableIfFunctionality#SEQAN_CTOR_ENABLE_IF 173 * @see EnableIfFunctionality#SEQAN_CTOR_DISABLE_IF 174 */ 175 176 // 177 // Example for enable-if function: 178 // 179 // template <typename TContainer> 180 // typename EnableIf< 181 // IsContainer<TContainer>, // 1st arg: enable-if condition 182 // typename Size<TContainer>::Type >::Type // 2nd arg: return type 183 // length(TContainer & cont) 184 // { 185 // SEQAN_CONCEPT_ASSERT((ContainerConcept<TContainer>)); 186 // return end(cont) - begin(cont); 187 // } 188 189 template <bool b, typename T> 190 struct EnableIf2; 191 192 template <bool b, typename T = void> 193 struct EnableIf2 194 { 195 typedef T Type; 196 }; 197 198 template <typename T> 199 struct EnableIf2<false, T> {}; 200 201 // ---------------------------------------------------------------------------- 202 // Metafunction DisableIf2 203 // ---------------------------------------------------------------------------- 204 205 /*! 206 * @mfn EnableIfFunctionality#DisableIf2 207 * @headerfile <seqan/basic.h> 208 * @deprecated Will be renamed to DisableIfC. 209 * @brief Metafunction to use for conditionally disabling code, bool version. 210 * 211 * @signature DisableIf2<BOOL, T = void>::Type 212 * 213 * @tparam BOOL The <tt>bool</tt> constant to evaluate for enabling/disabling. 214 * @tparam T Dummy, do not set. 215 * 216 * @return Type Set to <tt>T</tt>. Only defined if <tt>BOOL</tt> is <tt>false</tt>. This triggers the SFINAE behaviour 217 * in C++ which can be used to enable/disable functions. 218 * 219 * Do not use directly but use through the enable if/disable if macros. 220 * 221 * @see EnableIfFunctionality#SEQAN_FUNC_ENABLE_IF 222 * @see EnableIfFunctionality#SEQAN_FUNC_DISABLE_IF 223 * @see EnableIfFunctionality#SEQAN_CTOR_ENABLE_IF 224 * @see EnableIfFunctionality#SEQAN_CTOR_DISABLE_IF 225 */ 226 227 template <bool b, typename T> 228 struct DisableIf2; 229 230 template <bool b, typename T = void> 231 struct DisableIf2 232 { 233 typedef T Type; 234 }; 235 236 template <typename T> 237 struct DisableIf2<true, T> {}; 238 239 } // namespace seqan 240 241 // ============================================================================ 242 // Macros 243 // ============================================================================ 244 245 /*! 246 * @macro EnableIfFunctionality#SEQAN_CTOR_ENABLE_IF 247 * @headerfile <seqan/basic.h> 248 * @brief Bind the visibility of a constructor to an expression. 249 * 250 * @signature SEQAN_CTOR_ENABLE_IF(TCondition); 251 * 252 * @param TCondition Boolean type, one of <tt>True</tt> and <tt>False</tt> or a metafunction returning such a tag 253 * type. If <tt>True</tt> then the constructor is visible, otherwise, it is not. 254 * 255 * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a 256 * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value. The macro call must be used as the last dummy-argument of a constructor. 257 * 258 * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body. 259 * 260 * <b>Important:</b> The constructor to enable must be a function template and <tt>TCondition</tt> must include at 261 * least one template parameter of the function template. 262 * 263 * @section Example 264 * 265 * The following shows an example on how to properly use <tt>SEQAN_CTOR_ENABLE_IF</tt> as the last argument to the 266 * constructor and suppressing the unused variable warning for the dummy parameter. 267 * 268 * @snippet demos/dox/basic/enable_if.cpp enable if example constructor 269 */ 270 271 #define SEQAN_CTOR_ENABLE_IF(...) typename seqan::EnableIf<__VA_ARGS__>::Type * dummy = 0 272 273 /*! 274 * @macro EnableIfFunctionality#SEQAN_CTOR_DISABLE_IF 275 * @headerfile <seqan/basic.h> 276 * @brief Bind the visibility of a constructor to an expression. 277 * 278 * @signature SEQAN_CTOR_DISABLE_IF(TCondition); 279 * 280 * @param TCondition Boolean type, one of <tt>True</tt> and <tt>False</tt> or a metafunction returning such a tag 281 * type. If <tt>False</tt> then the constructor is visible, otherwise, it is not. 282 * 283 * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a 284 * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value. The macro call must be used as the last dummy-argument of a constructor. 285 * 286 * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body. 287 * 288 * <b>Important:</b> The constructor to disable must be a function template and <tt>TCondition</tt> must include at 289 * least one template parameter of the function template. 290 * 291 * @section Example 292 * 293 * The following shows an example on how to properly use <tt>SEQAN_CTOR_DISABLE_IF</tt> as the last argument to the 294 * constructor and suppressing the unused variable warning for the dummy parameter. 295 * 296 * @snippet demos/dox/basic/enable_if.cpp disable if example constructor 297 */ 298 299 #define SEQAN_CTOR_DISABLE_IF(...) typename seqan::DisableIf<__VA_ARGS__>::Type * dummy = 0 300 301 /*! 302 * @macro EnableIfFunctionality#SEQAN_FUNC_ENABLE_IF 303 * @headerfile <seqan/basic.h> 304 * @brief Bind the visibility of a function to an expression. 305 * 306 * @signature SEQAN_FUNC_ENABLE_IF(TCondition, TResult); 307 * 308 * @param TCondition Boolean type, one of <tt>True</tt> and <tt>False</tt> or a metafunction returning such a tag 309 * type. If <tt>True</tt> then the function is visible, otherwise, it is not. 310 * @param TResult The type that the function should have as the return type in case it is enabled. 311 * 312 * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a 313 * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value. The macro call must occur as the return type definition of the function. 314 * 315 * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body. 316 * 317 * <b>Important:</b> The function to enable must be a function template and <tt>TCondition</tt> must include at 318 * least one template parameter of the function template. 319 * 320 * @section Example 321 * 322 * The following shows an example on how to properly use <tt>SEQAN_FUNC_ENABLE_IF</tt> as the last argument to the 323 * constructor and suppressing the unused variable warning for the dummy parameter. 324 * 325 * @snippet demos/dox/basic/enable_if.cpp enable if example function 326 */ 327 328 #define SEQAN_FUNC_ENABLE_IF(...) typename seqan::EnableIf<__VA_ARGS__>::Type 329 330 /*! 331 * @macro EnableIfFunctionality#SEQAN_FUNC_DISABLE_IF 332 * @headerfile <seqan/basic.h> 333 * @brief Bind the visibility of a function to an expression. 334 * 335 * @signature SEQAN_FUNC_DISABLE_IF(TCondition, TResult); 336 * 337 * @param TCondition Boolean type, one of <tt>True</tt> and <tt>False</tt> or a metafunction returning such a tag 338 * type. If <tt>False</tt> then the function is visible, otherwise, it is not. 339 * @param TResult The type that the function should have as the return type in case it is enabled. 340 * 341 * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a 342 * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value. The macro call must occur as the return type definition of the function. 343 * 344 * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body. 345 * 346 * <b>Important:</b> The function to disable must be a function template and <tt>TCondition</tt> must include at least 347 * one template parameter of the function template. 348 * 349 * @section Example 350 * 351 * The following shows an example on how to properly use <tt>SEQAN_FUNC_DISABLE_IF</tt> as the last argument to the 352 * constructor and suppressing the unused variable warning for the dummy parameter. 353 * 354 * @snippet demos/dox/basic/enable_if.cpp disable if example function 355 */ 356 357 #define SEQAN_FUNC_DISABLE_IF(...) typename seqan::DisableIf<__VA_ARGS__>::Type 358 359 // ============================================================================ 360 // Functions 361 // ============================================================================ 362 363 #endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_METAPROGRAMMING_ENABLE_IF_H_ 364