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 // Metaprogramming control structures.
35 //
36 // This header defines metaprogramming control structure such as conditionals
37 // and loops.
38 // ==========================================================================
39 
40 #ifndef SEQAN_INCLUDE_SEQAN_BASIC_METAPROGRAMMING_CONTROL_H_
41 #define SEQAN_INCLUDE_SEQAN_BASIC_METAPROGRAMMING_CONTROL_H_
42 
43 namespace seqan {
44 
45 // ============================================================================
46 // Forwards
47 // ============================================================================
48 
49 // ============================================================================
50 // Tags, Classes, Enums
51 // ============================================================================
52 
53 // ============================================================================
54 // Metafunctions
55 // ============================================================================
56 
57 // ----------------------------------------------------------------------------
58 // Metafunction Switch;  Supporting Tags Case, NilCase.
59 // ----------------------------------------------------------------------------
60 
61 /*!
62  * @defgroup MetafunctionSwitch Switch Metafunction Types
63  * @brief Tags for the metafunction Switch and the metafunction itself.
64  *
65  * @section Example
66  *
67  * The following shows a complete example of using the Switch statement.
68  *
69  * @snippet demos/dox/basic/metaprogramming_switch.cpp switch demo
70  */
71 
72 // TODO(holtgrew): Use Tag<>?
73 /*!
74  * @tag MetafunctionSwitch#NilCase
75  * @brief Tag for terminating the case in Switch statement.
76  *
77  * @signature struct NilCase {};
78  */
79 
80 /*!
81  * @mfn MetafunctionSwitch#Case
82  * @brief Tag for one case.
83  *
84  * @signature template <int TAG, typename TResult, typename TNext>
85  *            struct Case;
86  *
87  * @tparam TAG     The <tt>int</tt> tag number to use.
88  * @tparam TResult The type to return in <tt>Case<...>::Type</tt> if matches.
89  * @tparam TNext   The next <tt>Case</tt>.
90  */
91 
92 /*!
93  * @mfn MetafunctionSwitch#Switch
94  * @brief Switch statement for metaprogramming.
95  *
96  * @signature Switch<TAG, TCase>::Type
97  *
98  * @tparam TAG   <tt>int</tt> with the current value.
99  * @tparam TCase First <tt>Case</tt> statement.
100  *
101  * @return Type The selected type.
102  */
103 
104 const int DEFAULT_ = ~(~0u >> 1); // initialize with the smallest int
105 
106 struct NilCase {};
107 
108 template <int TAG, typename Type_, typename Next_ = NilCase>
109 struct Case
110 {
111     enum { TAG_ = TAG };
112     typedef Type_ Type;
113     typedef Next_ Next;
114 };
115 
116 template <int TAG, typename Case_>
117 struct Switch
118 {
119     typedef typename Case_::Next NextCase_;
120     enum
121     {
122         CASE_TAG_ = Case_::TAG_,
123         FOUND_    = (CASE_TAG_ == TAG || CASE_TAG_ == DEFAULT_)
124     };
125 
126     typedef typename IfC<FOUND_,
127                          typename Case_::Type,
128                          typename Switch<TAG, NextCase_>::Type
129                          >::Type Type;
130 };
131 
132 template <int TAG>
133 struct Switch<TAG, NilCase>
134 {
135     typedef NilCase Type;
136 };
137 
138 // ----------------------------------------------------------------------------
139 // Metafunction Loop
140 // ----------------------------------------------------------------------------
141 
142 /*!
143  * @class Loop
144  * @headerfile <seqan/basic.h>
145  * @brief Helper for loops.
146  *
147  * @signature template <typename TWorker, unsigned COUNT>
148  *            struct Loop;
149  *
150  * @tparam TWorker A struct with a static inline void function called <tt>body</tt>.  <tt>body</tt> should have two
151  *                 parameters, one for passing in values and state from the outside and the second is an int.  The
152  *                 function will be called <tt>COUNT</tt> times with the same reference for the first one and the values
153  *                 <tt>COUNT</tt>, <tt>COUNT - 1</tt>, ..., <tt>1</tt> for the second parameter.
154  * @tparam COUNT   An <tt>int</tt> constant.
155  *
156  * @section Example
157  *
158  * We define the following worker to print an integer.  The first argument is of <tt>Nothing</tt> as a dummy.  Note that
159  * the parameter is not const.
160  *
161  * @snippet demos/dox/basic/metaprogramming_control.cpp print worker
162  *
163  * The following shows an example calling <tt>PrintWorker::body()</tt> through Loop.  We have to create a local variable
164  * since the first parameter is not const.  The reason for this is that the parameter can also be used for a mutable
165  * object that holds some state.
166  *
167  * @snippet demos/dox/basic/metaprogramming_control.cpp print worker call loop reverse
168  *
169  * @see LoopReverse
170  *
171  * @fn Loop::run
172  * @brief Run the loop body.
173  *
174  * @signature Loop::run(arg, i);
175  *
176  * @param[in,out] arg The argument to pass to the worker's <tt>body()</tt> function.
177  * @param[in]     i   The <tt>int</tt> passed to the <tt>body()</tt> function.
178  */
179 
180 // Example of a loop Worker class.  Could be removed, serves no
181 // purpose.
182 struct WorkerNothing
183 {
184     template <typename Arg>
185     static inline void body(Arg & /*arg*/, int /*I*/)
186     {}
187 };
188 
189 template <typename Worker, int I>
190 class Loop {
191 public:
192     template <typename Arg>
193     static inline void run(Arg & arg)
194     {
195         Loop<Worker, I - 1>::run(arg);
196         Worker::body(arg, I);
197     }
198 };
199 
200 template <typename Worker>
201 class Loop<Worker, 0>
202 {
203 public:
204     // end of loop
205     template <typename Arg>
206     static inline void run(Arg &)
207     {}
208 };
209 
210 // ----------------------------------------------------------------------------
211 // Metafunction LoopReverse
212 // ----------------------------------------------------------------------------
213 
214 /*!
215  * @class LoopReverse
216  * @brief Helper for reverse loops.
217  *
218  * @headerfile <seqan/basic.h>
219  *
220  * @signature template <typename TWorker, unsigned COUNT>
221  *            struct LoopReverse;
222  *
223  * @tparam TWorker A struct with a static inline void function called <tt>body</tt>.  <tt>body</tt> should have two
224  *                 parameters, one for passing in values and state from the outside and the second is an int.  The
225  *                 function will be called <tt>COUNT</tt> times with the same reference for the first one and the values
226  *                 <tt>COUNT</tt>, <tt>COUNT - 1</tt>, ..., <tt>1</tt> for the second parameter.
227  * @tparam COUNT   An <tt>int</tt> constant.
228  *
229  * @section Example
230  *
231  * We define the following worker to print an integer.  The first argument is of <tt>Nothing</tt> as a dummy.  Note that
232  * the parameter is not const.
233  *
234  * @snippet demos/dox/basic/metaprogramming_control.cpp print worker
235  *
236  * The following shows an example calling <tt>PrintWorker::body()</tt> through LoopReverse.  We have to create a local
237  * variable since the first parameter is not const.  The reason for this is that the parameter can also be used for a
238  * mutable object that holds some state.
239  *
240  * @snippet demos/dox/basic/metaprogramming_control.cpp print worker call loop
241  *
242  * @see Loop
243  *
244  * @fn LoopReverse::run
245  * @brief Run the loop body.
246  *
247  * @signature LoopReverse::run(arg, i);
248  *
249  * @param[in,out] arg The argument to pass to the worker's <tt>body()</tt> function.
250  * @param[in]     i   The <tt>int</tt> passed to the <tt>body()</tt> function.
251  */
252 
253 template <typename Worker, int I>
254 class LoopReverse
255 {
256 public:
257     template <typename Arg>
258     static inline void run(Arg & arg)
259     {
260         Worker::body(arg, I);
261         LoopReverse<Worker, I - 1>::run(arg);
262     }
263 };
264 
265 template <typename Worker>
266 class LoopReverse<Worker, 0>
267 {
268   public:
269     // end of loop
270     template <typename Arg>
271     static inline void run(Arg &) {}
272 };
273 
274 // ============================================================================
275 // Functions
276 // ============================================================================
277 
278 }  // namespace seqan
279 
280 #endif  // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_METAPROGRAMMING_CONTROL_H_
281