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