// bsls_macrorepeat.h -*-C++-*- #ifndef INCLUDED_BSLS_MACROREPEAT #define INCLUDED_BSLS_MACROREPEAT #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: repeat a macro invocation with different numeric arguments. // //@CLASSES: // //@MACROS: // BSLS_MACROREPEAT(N, MACRO): Invoke 'MACRO(1) MACRO(2) ... MACRO(N)' // BSLS_MACROREPEAT_COMMA(N, MACRO): 'N' comma-separated invocations of 'MACRO' // BSLS_MACROREPEAT_SEP(N, MACRO, S): 'N' invocations of 'MACRO' separated by S // //@SEE_ALSO: // //@DESCRIPTION: This component provides a set of macros that expand to multiple // repetitions of a user-specified "repetition phrase". The repetition phrase // is specified as macro that is invoked multiple times in each invocation of a // 'BSLS_MACROREPEAT*' macro. For example: //.. // #define FOO(n) foo ## n // doit(BSLS_MACROREPEAT_COMMA(5, FOO)); //.. // will expand FOO(n) with arguments 1 through 5, inserting commas between the // expansions, resulting in: //.. // doit(foo1, foo2, foo3, foo4, foo5); //.. // Use of these macros is less error-prone and often more compact than manually // repeating the specified pattern. In addition, it is sometimes more readable // than the cut-and-paste alternative because the reader does not need to // examine each argument to verify that it forms a linear sequence. // // Each of these macros can appear within the repetition phrase of another of // these macros but, because of limitations in the C proprocessor language, // none of these macros can appear (directly or indirectly) within its own // repetition phrase. // ///Usage ///----- // The following examples demonstrate potential uses of the macros in this // component. // ///Example 1: Repeated Template Instantiation /// - - - - - - - - - - - - - - - - - - - - - // In this example, we wish to explicitly instantiate a template with a // sequence of integer values. First, assume a function template 'foo<V>' that // adds the (compile-time) value 'V' to a global 'total' each time it is // called: //.. // int total = 0; // template <int V> void foo() { total += V; } //.. // Now, if we instantiate and call 'foo<X>()' once for each 'X' in the range // '2' to '6'. To do that, we create a macro, 'FOO_STMNT(X)' which and calls // 'foo<X+1>' (i.e., 'FOO_STMNT(1)' will call 'foo<2>()'). Then we invoke // 'FOO_STMNT' 5 times with arguments 1, 2, 3, 4, and 5 using the // 'BSLS_MACROREPEAT' macro: //.. // int main() { // // #define FOO_STMNT(X) foo<X+1>(); // Semicolon at end of each statement // BSLS_MACROREPEAT(5, FOO_STMNT) // assert(20 == total); // return 0; // } //.. // ///Example 2: Repeated Function Arguments /// - - - - - - - - - - - - - - - - - - - // In this example, we supply as series of identical arguments to a function // invocation, using 'BSLS_MACROREPEAT_COMMA'. First, assume a function, // 'fmtQuartet' that takes four integer arguments and formats them into a // string: //.. // #include <cstring> // #include <cstdio> // // void fmtQuartet(char *result, int a, int b, int c, int d) { // std::sprintf(result, "%d %d %d %d", a, b, c, d); // } //.. // Now we wish to invoke this function, but in a context where the last three // arguments are always the same as each other. For this situation we define a // macro 'X(x)' that ignores its argument and simply expands to an unchanging // set of tokens. If the repeated argument is named 'i', then the expansion of // 'X(x)' is simply '(i)': //.. // int main() { // char buffer[20]; // int i = 8; // #define X(x) (i) //.. // Finally, we invoke macro 'X(x)' three times within the argument list of // 'fmtQuart'. We use 'BSLS_MACROREPEAT_COMMA' for these invocations, as it // inserts a comma between each repetition: //.. // fmtQuartet(buffer, "%d %d %d %d", 7, BSLS_MACROREPEAT_COMMA(3, X)); // assert(0 == std::strcmp(buffer, "7 8 8 8")); // return 0; // } //.. // ///Example 3: Bitmask Computation /// - - - - - - - - - - - - - - - // In this example, we Compute (at compile time) a 7-bit mask. First, we // defined a macro 'BITVAL' that computes the value of a single bit 'B' in the // mask: //.. // #define BITVAL(B) (1 << (B - 1)) //.. // Then we use the 'BSLS_MACROREPEAT_SEP' to invoke 'BITVAL' 7 times, // separating the repetitions with the bitwise OR operator: //.. // const unsigned mask = BSLS_MACROREPEAT_SEP(7, BITVAL, |); // // int main() { // assert(127 == mask); // return 0; // } //.. #define BSLS_MACROREPEAT(N, MACRO) BSLS_MACROREPEAT_##N(MACRO) // Expand to 'N' invocations of 'MACRO(x)', where 'x' in each invocation is // the next number in the sequence from '1' to 'N'. If 'N' is '0', then // the expansion is empty. For example 'BSLS_MACROREPEAT(3, XYZ)' expands // to 'XYZ(1) XYZ(2) XYZ(3)'. The behavior is undefined unless 'N' is a // decimal integer (or is a macro that expands to a decimal integer) in the // range 0 to 20. Note that 'MACRO' is typically a macro with one // argument, but may also be a function or functor. #define BSLS_MACROREPEAT_COMMA(N, MACRO) BSLS_MACROREPEAT_C##N(MACRO) // Expand to 'N' comma-separated invocations of 'MACRO(x)', where 'x' in // each invocation is the next number in the sequence from '1' to 'N'. If // 'N' is '0', then the expansion is empty. For example // 'BSLS_MACROREPEAT_COMMA(3, XYZ)' expands to 'XYZ(1), XYZ(2), XYZ(3)'. // The behavior is undefined unless 'N' is a decimal integer (or is a macro // that expands to a decimal integer) in the range 0 to 20. Note that // 'MACRO' is typically a macro with one argument, but may also be a // function or functor. #define BSLS_MACROREPEAT_SEP(N, MACRO, S) BSLS_MACROREPEAT_S##N(MACRO, S) // Expand to 'N' invocations of 'MACRO(x)' separated by the token sequence // 'S', where 'x' in each invocation is the next number in the sequence // from '1' to 'N'. If 'N' is '0', then the expansion is empty. For // example 'BSLS_MACROREPEAT_SEP(3, XYZ, ;)' expands to 'XYZ(1) ; XYZ(2) ; // XYZ(3)'. The behavior is undefined unless 'N' is a decimal integer (or // is a macro that expands to a decimal integer) in the range 0 to 20. // Note that 'MACRO' is typically a macro with one argument, but may also // be a function or functor. // ============================================================================ // IMPLEMENTATION MACROS // ============================================================================ #define BSLS_MACROREPEAT_0(MACRO) #define BSLS_MACROREPEAT_1(MACRO) MACRO(1) #define BSLS_MACROREPEAT_2(MACRO) BSLS_MACROREPEAT_1(MACRO) MACRO(2) #define BSLS_MACROREPEAT_3(MACRO) BSLS_MACROREPEAT_2(MACRO) MACRO(3) #define BSLS_MACROREPEAT_4(MACRO) BSLS_MACROREPEAT_3(MACRO) MACRO(4) #define BSLS_MACROREPEAT_5(MACRO) BSLS_MACROREPEAT_4(MACRO) MACRO(5) #define BSLS_MACROREPEAT_6(MACRO) BSLS_MACROREPEAT_5(MACRO) MACRO(6) #define BSLS_MACROREPEAT_7(MACRO) BSLS_MACROREPEAT_6(MACRO) MACRO(7) #define BSLS_MACROREPEAT_8(MACRO) BSLS_MACROREPEAT_7(MACRO) MACRO(8) #define BSLS_MACROREPEAT_9(MACRO) BSLS_MACROREPEAT_8(MACRO) MACRO(9) #define BSLS_MACROREPEAT_10(MACRO) BSLS_MACROREPEAT_9(MACRO) MACRO(10) #define BSLS_MACROREPEAT_11(MACRO) BSLS_MACROREPEAT_10(MACRO) MACRO(11) #define BSLS_MACROREPEAT_12(MACRO) BSLS_MACROREPEAT_11(MACRO) MACRO(12) #define BSLS_MACROREPEAT_13(MACRO) BSLS_MACROREPEAT_12(MACRO) MACRO(13) #define BSLS_MACROREPEAT_14(MACRO) BSLS_MACROREPEAT_13(MACRO) MACRO(14) #define BSLS_MACROREPEAT_15(MACRO) BSLS_MACROREPEAT_14(MACRO) MACRO(15) #define BSLS_MACROREPEAT_16(MACRO) BSLS_MACROREPEAT_15(MACRO) MACRO(16) #define BSLS_MACROREPEAT_17(MACRO) BSLS_MACROREPEAT_16(MACRO) MACRO(17) #define BSLS_MACROREPEAT_18(MACRO) BSLS_MACROREPEAT_17(MACRO) MACRO(18) #define BSLS_MACROREPEAT_19(MACRO) BSLS_MACROREPEAT_18(MACRO) MACRO(19) #define BSLS_MACROREPEAT_20(MACRO) BSLS_MACROREPEAT_19(MACRO) MACRO(20) #define BSLS_MACROREPEAT_C0(MACRO) #define BSLS_MACROREPEAT_C1(MACRO) MACRO(1) #define BSLS_MACROREPEAT_C2(MACRO) BSLS_MACROREPEAT_C1(MACRO), MACRO(2) #define BSLS_MACROREPEAT_C3(MACRO) BSLS_MACROREPEAT_C2(MACRO), MACRO(3) #define BSLS_MACROREPEAT_C4(MACRO) BSLS_MACROREPEAT_C3(MACRO), MACRO(4) #define BSLS_MACROREPEAT_C5(MACRO) BSLS_MACROREPEAT_C4(MACRO), MACRO(5) #define BSLS_MACROREPEAT_C6(MACRO) BSLS_MACROREPEAT_C5(MACRO), MACRO(6) #define BSLS_MACROREPEAT_C7(MACRO) BSLS_MACROREPEAT_C6(MACRO), MACRO(7) #define BSLS_MACROREPEAT_C8(MACRO) BSLS_MACROREPEAT_C7(MACRO), MACRO(8) #define BSLS_MACROREPEAT_C9(MACRO) BSLS_MACROREPEAT_C8(MACRO), MACRO(9) #define BSLS_MACROREPEAT_C10(MACRO) BSLS_MACROREPEAT_C9(MACRO), MACRO(10) #define BSLS_MACROREPEAT_C11(MACRO) BSLS_MACROREPEAT_C10(MACRO), MACRO(11) #define BSLS_MACROREPEAT_C12(MACRO) BSLS_MACROREPEAT_C11(MACRO), MACRO(12) #define BSLS_MACROREPEAT_C13(MACRO) BSLS_MACROREPEAT_C12(MACRO), MACRO(13) #define BSLS_MACROREPEAT_C14(MACRO) BSLS_MACROREPEAT_C13(MACRO), MACRO(14) #define BSLS_MACROREPEAT_C15(MACRO) BSLS_MACROREPEAT_C14(MACRO), MACRO(15) #define BSLS_MACROREPEAT_C16(MACRO) BSLS_MACROREPEAT_C15(MACRO), MACRO(16) #define BSLS_MACROREPEAT_C17(MACRO) BSLS_MACROREPEAT_C16(MACRO), MACRO(17) #define BSLS_MACROREPEAT_C18(MACRO) BSLS_MACROREPEAT_C17(MACRO), MACRO(18) #define BSLS_MACROREPEAT_C19(MACRO) BSLS_MACROREPEAT_C18(MACRO), MACRO(19) #define BSLS_MACROREPEAT_C20(MACRO) BSLS_MACROREPEAT_C19(MACRO), MACRO(20) #define BSLS_MACROREPEAT_S0(MACRO,S) #define BSLS_MACROREPEAT_S1(MACRO,S) MACRO(1) #define BSLS_MACROREPEAT_S2(MACRO,S) BSLS_MACROREPEAT_S1(MACRO,S) S MACRO(2) #define BSLS_MACROREPEAT_S3(MACRO,S) BSLS_MACROREPEAT_S2(MACRO,S) S MACRO(3) #define BSLS_MACROREPEAT_S4(MACRO,S) BSLS_MACROREPEAT_S3(MACRO,S) S MACRO(4) #define BSLS_MACROREPEAT_S5(MACRO,S) BSLS_MACROREPEAT_S4(MACRO,S) S MACRO(5) #define BSLS_MACROREPEAT_S6(MACRO,S) BSLS_MACROREPEAT_S5(MACRO,S) S MACRO(6) #define BSLS_MACROREPEAT_S7(MACRO,S) BSLS_MACROREPEAT_S6(MACRO,S) S MACRO(7) #define BSLS_MACROREPEAT_S8(MACRO,S) BSLS_MACROREPEAT_S7(MACRO,S) S MACRO(8) #define BSLS_MACROREPEAT_S9(MACRO,S) BSLS_MACROREPEAT_S8(MACRO,S) S MACRO(9) #define BSLS_MACROREPEAT_S10(MACRO,S) BSLS_MACROREPEAT_S9(MACRO,S) S MACRO(10) #define BSLS_MACROREPEAT_S11(MACRO,S) BSLS_MACROREPEAT_S10(MACRO,S) S MACRO(11) #define BSLS_MACROREPEAT_S12(MACRO,S) BSLS_MACROREPEAT_S11(MACRO,S) S MACRO(12) #define BSLS_MACROREPEAT_S13(MACRO,S) BSLS_MACROREPEAT_S12(MACRO,S) S MACRO(13) #define BSLS_MACROREPEAT_S14(MACRO,S) BSLS_MACROREPEAT_S13(MACRO,S) S MACRO(14) #define BSLS_MACROREPEAT_S15(MACRO,S) BSLS_MACROREPEAT_S14(MACRO,S) S MACRO(15) #define BSLS_MACROREPEAT_S16(MACRO,S) BSLS_MACROREPEAT_S15(MACRO,S) S MACRO(16) #define BSLS_MACROREPEAT_S17(MACRO,S) BSLS_MACROREPEAT_S16(MACRO,S) S MACRO(17) #define BSLS_MACROREPEAT_S18(MACRO,S) BSLS_MACROREPEAT_S17(MACRO,S) S MACRO(18) #define BSLS_MACROREPEAT_S19(MACRO,S) BSLS_MACROREPEAT_S18(MACRO,S) S MACRO(19) #define BSLS_MACROREPEAT_S20(MACRO,S) BSLS_MACROREPEAT_S19(MACRO,S) S MACRO(20) #endif // ! defined(INCLUDED_BSLS_MACROREPEAT) // ---------------------------------------------------------------------------- // Copyright 2013 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------