diff --git a/doc/Appendix A   An Introduction to Preprocessor Metaprogramming.html b/doc/Appendix A   An Introduction to Preprocessor Metaprogramming.html new file mode 100644 index 0000000..c713012 --- /dev/null +++ b/doc/Appendix A   An Introduction to Preprocessor Metaprogramming.html @@ -0,0 +1,2494 @@ + + + + + + Appendix A   An Introduction to Preprocessor Metaprogramming + + +
+
+

Appendix A   An Introduction to Preprocessor + Metaprogramming

+ + + + + + + + + + + + + +
Copyright:From "C++ Template Metaprogramming," by David Abrahams and + Aleksey Gurtovoy. Copyright (c) 2005 by Pearson Education, Inc. + Reprinted with permission.
ISBN:0321227255
+
+

A.1   Motivation

+

Even with the full power of template metaprogramming and the Boost Metaprogramming library + at our disposal, some C++ coding jobs still require a great deal of + boilerplate code repetition. We saw one example in Chapter 5, when we + implemented tiny_size:

+
template <class T0, class T1, class T2>
+struct tiny_size
+  : mpl::int_<3> {};
+
+ + +

Aside from the repeated pattern in the parameter list of the primary + template above, there are three partial specializations below, which + also follow a predictable pattern:

+
template <class T0, class T1>
+struct tiny_size<T0,T1,none>
+  : mpl::int_<2> {};
+
+template <class T0>
+struct tiny_size<T0,none,none>
+  : mpl::int_<1> {};
+
+template <>
+struct tiny_size<none,none,none>
+  : mpl::int_<0> {};
+
+ + +

In this case there is only a small amount of code with such a + "mechanical" flavor, but had we been implementing large instead of tiny, there might easily have been a great + deal more. When the number of instances of a pattern grows beyond two + or three, writing them by hand tends to become error-prone. Perhaps + more importantly, the code gets hard to read, because the important + abstraction in the code is really the pattern, not the individual + instances.

+
+

A.1.1   Code Generation

+

Rather than being written out by hand, mechanical-looking code + should really be generated mechanically. Having written a program to + spit out instances of the code pattern, a library author has two + choices: She can either ship pre-generated source code files, or she + can ship the generator itself. Either approach has drawbacks. If + clients only get the generated source, they are stuck with whatever + the library author generated—and experience shows that if they are + happy with three instances of a pattern today, someone will need + four tomorrow. If clients get the generator program, on the other + hand, they also need the resources to execute it (e.g., + interpreters), and they must integrate the generator into their + build processes...

+
+
+

A.1.2   Enter the Preprocessor

+

...unless the generator is a preprocessor metaprogram. Though not + designed for that purpose, the C and C++ preprocessors can be made + to execute sophisticated programs during the preprocessing phase of + compilation. Users can control the code generation process with + preprocessor #defines + in code or -D + options on the compiler's command line, making build integration + trivial. For example, we might parameterize the primary tiny_size template above as follows:

+
#include <boost/preprocessor/repetition/enum_params.hpp>
+
+#ifndef TINY_MAX_SIZE
+#  define TINY_MAX_SIZE 3  // default maximum size is 3
+#endif
+
+template <BOOST_PP_ENUM_PARAMS(TINY_MAX_SIZE, class T)>
+struct tiny_size
+  : mpl::int_<TINY_MAX_SIZE>
+{};
+
+ + +

To test the metaprogram, run your compiler in its "preprocessing" + mode (usually the -E + option), with the Boost root directory in your #include path. For instance:[1]

+
g++ -P -E -Ipath/to/boost_1_32_0 -I. test.cpp
+
+ + + + + + + + + +
[1]GCC's -P + option inhibits the generation of source file and line number + markers in preprocessed output.
+

Given the appropriate metaprograms, users would be able to adjust + not only the number of parameters to tiny_size, but the maximum size of the + entire tiny + implementation just by #define-ing + TINY_MAX_SIZE.

+

The Boost Preprocessor library [MK04] plays a role in preprocessor + metaprogramming similar to the one played by the MPL in template + metaprogramming: It supplies a framework of high-level components + (like BOOST_PP_ENUM_PARAMS) + that make otherwise-painful metaprogramming jobs approachable. In + this appendix we won't attempt to cover nitty-gritty details of how + the preprocessor works, nor principles of preprocessor + metaprogramming in general, nor even many details of how the + Preprocessor library works. We will show you + enough at a high level that you'll be able to use the library + productively and learn the rest on your own.

+ + + + + + + + +
[MK04]Paul Mensonides and Vesa Karvonen. "The Boost Preprocessor + Library." http://www.boost.org/libs/preprocessor.
+
+
+
+

A.2   Fundamental + Abstractions of the Preprocessor

+

We began our discussion of template metaprogramming in Chapter 2 by + describing its metadata (potential template arguments) and + metafunctions (class templates). On the basis of those two fundamental + abstractions, we built up the entire picture of compile-time + computation covered in the rest of this book. In this section we'll + lay a similar foundation for the preprocessor metaprogrammer. Some of + what we cover here may be a review for you, but it's important to + identify the basic concepts going into detail.

+
+

A.2.1   Preprocessing Tokens

+

The fundamental unit of data in the preprocessor is the preprocessing + token. Preprocessing tokens correspond roughly to the + tokens you're used to working with in C++, such as identifiers, + operator symbols, and literals. Technically, there are some + differences between preprocessing tokens and regular tokens + (see section 2 of the C++ standard for details), but they can be + ignored for the purposes of this discussion. In fact, we'll be using + the terms interchangeably here.

+
+
+

A.2.2   Macros

+

Preprocessor macros come in two flavors. Object-like + macros can be defined this way:

+
+
+
#define + identifier replacement-list
+
+
+ +

where the identifier names the macro being defined, and replacement-list + is a sequence of zero or more tokens. Where the identifier + appears in subsequent program text, it is expanded + by the preprocessor into its replacement-list.

+

Function-like macros, which act as the + "metafunctions of the preprocessing phase," are defined as follows:

+
+
+
#define + identifier(a1, a2, + ... an) replacement-list
+
+
+ +

where each ai is an identifier naming a macro + parameter. When the macro name appears in subsequent + program text followed by a suitable argument list, it is expanded + into its replacement-list, except that each argument is + substituted for the corresponding parameter where it appears in the + replacement-list.[2]

+ + + + + + + + +
[2]We have omitted many details of how macro expansion works. + We encourage you to take a few minutes to study section 16.3 + of the C++ standard, which describes that process in + straightforward terms.
+
+
+

A.2.3   Macro Arguments

+
+

Definition

+

A macro argument is a nonempty sequence of:

+
    +
  • Preprocessing tokens other than commas or parentheses, and/or
  • +
  • Preprocessing tokens surrounded by matched pairs of + parentheses.
  • +
+
+

This definition has consequences for preprocessor metaprogramming + that must not be underestimated. Note, first of all, that the + following tokens have special status:

+
+
,  (  )
+
+ +

As a result, a macro argument can never contain an unmatched + parenthesis, or a comma that is not surrounded by matched + parentheses. For example, both lines following the definition of FOO + below are ill-formed:

+
#define FOO(X) X // Unary identity macro
+FOO(,)           // un-parenthesized comma or two empty arguments
+FOO())           // unmatched parenthesis or missing argument
+
+ +

Note also that the following tokens do not have special + status; the preprocessor knows nothing about matched pairs of + braces, brackets, or angle brackets:

+
+
{  }  [  ]  <  >
+
+ +

As a result, these lines are also ill-formed:

+
FOO(std::pair<int, long>)                // two arguments
+FOO({ int x = 1, y = 2; return x+y; })   // two arguments
+
+ +

It is possible to pass either string of tokens above as + part of a single macro argument, provided it is parenthesized:

+
FOO((std::pair<int,int>))                 // one argument
+FOO(({ int x = 1, y = 2; return x+y; }))  // one argument
+
+ +

However, because of the special status of commas, it is impossible + to strip parentheses from a macro argument without knowing the + number of comma-separated token sequences it contains.[3] If you are writing a macro + that needs to be able to accept an argument containing a variable + number of commas, your users will either have to parenthesize that + argument and pass you the number of comma-separated token + sequences as an additional argument, or they will have to encode the + same information in one of the preprocessor data structures covered + later in this appendix.

+ + + + + + + + +
[3](1, 2) The C99 preprocessor, by virtue + of its variadic macros, can do that and more. The C++ + standardization committee is likely to adopt C99's + preprocessor extensions for the next version of the C++ + standard.
+
+
+
+

A.3   Preprocessor Library + Structure

+

Since in-depth coverage of the Boost Preprocessor library is beyond + the scope of this book, we'll try to give you the tools to + gain an in-depth understanding of the library here. To do that, you'll + need to use the electronic Preprocessor library documentation, which + begins with the index.html file in the libs/preprocessor/ subdirectory of your + Boost installation.

+

On the left of your browser window you'll see an index, and if you + follow the "Headers" link, it will reveal the structure of the boost/preprocessor/ directory. Most of the + library's headers are grouped into subdirectories according to related + functionality. The top-level directory contains only a few headers + that provide general-purpose macros, along with a header for each + subdirectory that simply #includes + all the headers in that subdirectory. For example, boost/preprocessor/selection.hpp does + nothing more than to #include + the min.hpp + and max.hpp + headers that comprise the contents of boost/preprocessor/selection/. The headers + whose names don't correspond to subdirectories generally + declare a macro whose name is the same as the name of the header, + without the extension, and with a BOOST_PP_ prefix. For example, boost/preprocessor/selection/max.hpp + declares BOOST_PP_MAX.

+

You'll also notice that often a header will declare an additional + macro with a _D, + _R, or _Z suffix.[4] + For instance, boost/preprocessor/selection/max.hpp + also declares BOOST_PP_MAX_D. + For the purposes of this appendix, you should ignore those macros. + Eventually you will want to understand how they can be used to + optimize preprocessing speed; consult the Topics section of the + library documentation under the subheading "reentrancy" for that + information.

+ + + + + + + + +
[4]Macros with _1ST, + _2ND, + or _3RD + suffixes, if they appear, should be ignored for a different + reason: They are deprecated and will be removed from the library + soon.
+
+
+

A.4   Preprocessor + Library Abstractions

+

In this section we'll discuss the basic abstractions of the + Preprocessor library, and give some simple examples of each.

+
+

A.4.1   Repetition

+

The repeated generation of class + T0, class T1... class Tn + that we achieved using BOOST_PP_ENUM_PARAMS + was a specific case of the general concept of horizontal + repetition. The library also has a concept of vertical + repetition, which we'll get to in a moment. Horizontal repetition + macros are all found in the library's repetition/ subdirectory.

+
+

A.4.1.1   Horizontal Repetition

+

To generate the tiny_size + specializations using horizontal repetition, we might write the + following:

+
#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+
+#define TINY_print(z, n, data) data
+
+#define TINY_size(z, n, unused)                                 \
+  template <BOOST_PP_ENUM_PARAMS(n, class T)>                   \
+  struct tiny_size<                                             \
+      BOOST_PP_ENUM_PARAMS(n,T)                                 \
+      BOOST_PP_COMMA_IF(n)                                      \
+      BOOST_PP_ENUM(                                            \
+          BOOST_PP_SUB(TINY_MAX_SIZE,n), TINY_print, none)      \
+  >                                                             \
+    : mpl::int_<n> {};
+
+BOOST_PP_REPEAT(TINY_MAX_SIZE, TINY_size, ~)
+
+#undef TINY_size
+#undef TINY_print
+
+ +

The code generation process is kicked off by calling BOOST_PP_REPEAT, a higher-order + macro that repeatedly invokes the macro named by its + second argument (TINY_size). + The first argument specifies the number of repeated invocations, + and the third one can be any data; it is passed on unchanged to + the macro being invoked. In this case, TINY_size doesn't use that data, so + the choice to pass ~ + was arbitrary.[5]

+ + + + + + + + +
[5]~ + is not an entirely arbitrary choice. Both @ and $ might have been good choices, + except that they are technically not part of the basic + character set that C++ implementations are required to + support. An identifier like ignored might be subject to + macro expansion, leading to unexpected results.
+

Each time the TINY_size + macro is invoked by BOOST_PP_REPEAT, + it generates a different specialization of tiny_size. The macro accepts three + parameters.

+
    +
  • z + is related to the _Z + macro suffix we mentioned earlier. You'll never need to use it + except for optimization purposes, and can safely ignore it for + now.
  • +
  • n + is the repetition index. In repeated invocations of TINY_size, n will be 0, then 1, then 2, and so on.
  • +
  • unused, + in this case, will be ~ + on each repetition. In general, the final argument to a macro + invoked by BOOST_PP_REPEAT + is always the same as its invoker's final argument.
  • +
+

Because its replacement-list covers several lines, all + but the last line of TINY_size + is continued with a trailing backslash. The first few of those + lines just invoke BOOST_PP_ENUM_PARAMS + (which we already used in the primary template) to generate + comma-separated lists, so each invocation of TINY_size produces something + equivalent to:[6]

+
template <class T0, class T1, ... class Tn-1>
+struct tiny_size<
+    T0, T1, ... Tn-1
+    ...more... 
+> 
+  : mpl::int_<n> {};
+
+ + + + + + + + +
[6]Note that the line continuation characters and + the newlines following them are removed by the preprocessor, + so the resulting code actually appears on a single line in + the preprocessed output.
+ +

BOOST_PP_COMMA_IF + generates a comma if its numeric argument is not 0. When n is 0, the list generated by the preceding + line will be empty, and a leading comma directly following the < + character would be ill-formed.

+

The next line uses BOOST_PP_ENUM + to generate TINY_MAX_SIZE-n + comma-separated copies of none. + BOOST_PP_ENUM + is just like BOOST_PP_REPEAT + except that it generates commas between repetitions, so its second + argument (TINY_print, + here) must have the same signature as TINY_size. In this case, TINY_print ignores its repetition + index n, + and simply yields its third argument, none.

+

BOOST_PP_SUB + implements token subtraction. It's crucial to understand that + although the preprocessor itself can evaluate ordinary + arithmetic expressions:

+
#define X 3
+...
+#if X - 1 > 0  // OK
+  whatever
+#endif
+
+ + +

preprocessor metaprograms can only operate on tokens. + Normally, when a macro in the Preprocessor library expects a + numeric argument, it must be passed as a single token. If we had + written TINY_MAX_SIZE-n + instead of BOOST_PP_SUB(TINY_MAX_SIZE,n) + above, the first argument to BOOST_PP_ENUM + would have contained three tokens at each invocation: first 3-0, then 3-1, and finally 3-2. BOOST_PP_SUB, though, generates + single-token results: first 3, + then 2, + and finally 1, + in successive repetitions.

+ +
+
+

A.4.1.2   Vertical Repetition

+

If you send the previous example through your preprocessor, + you'll see one long line containing something like this:

+
template <> struct tiny_size< none , none , none > : mpl::int_<0>
+ {}; template < class T0> struct tiny_size< T0 , none , none > :
+mpl::int_<1> {}; template < class T0 , class T1> struct tiny_size
+< T0 , T1 , none > : mpl::int_<2> {};
+
+ +

The distinguishing feature of horizontal repetition is that all + instances of the repeated pattern are generated on the same line + of preprocessed output. For some jobs, like generating the primary + tiny_size + template, that's perfectly appropriate. In this case, however, + there are at least two disadvantages.

+
    +
  1. It's hard to verify that our metaprogram is doing the right + thing without reformatting the resulting code by hand.
  2. +
  3. The efficiency of nested horizontal repetitions varies widely + across preprocessors. Each specialization generated by means of + horizontal repetition contains three other horizontal + repetitions: two invocations of BOOST_PP_ENUM_PARAMS and one + invocation of BOOST_PP_ENUM. + When TINY_MAX_SIZE + is 3, + you'll probably never care, but on at least one preprocessor + still in use today, compilation begins to slow noticeably when TINY_MAX_SIZE + reaches 8.[7]
  4. +
+
+ + + + + + + + +
[7]That said, other preprocessors can handle 256 * 256 + nested repetitions without any speed problems whatsoever.
+
+

The solution to these problems, naturally, is vertical + repetition, which generates instances of a pattern + across multiple lines. The Preprocessor library provides two means + of vertical repetition: local iteration and file + iteration.

+
+

Local Iteration

+

The most expedient way to demonstrate local iteration in our + example is to replace the invocation of BOOST_PP_REPEAT with the following:

+
#include <boost/preprocessor/iteration/local.hpp>
+
+#define BOOST_PP_LOCAL_MACRO(n)   TINY_size(~, n, ~)
+#define BOOST_PP_LOCAL_LIMITS     (0, TINY_MAX_SIZE - 1)
+#include BOOST_PP_LOCAL_ITERATE()
+
+ +

Local iteration repeatedly invokes the user-defined macro with + the special name BOOST_PP_LOCAL_MACRO, + whose argument will be an iteration index. Since we already had + TINY_size + lying around, we've just defined BOOST_PP_LOCAL_MACRO to invoke it. + The range of iteration indices are given by another user-defined + macro, BOOST_PP_LOCAL_LIMITS, + which must expand to a parenthesized pair of integer values + representing the inclusive range of index values + passed to BOOST_PP_LOCAL_MACRO. + Note that this is one of the rare places where the library + expects a numeric argument that can be an expression consisting + of multiple tokens.

+

Finally, the repetition is initiated by #include-ing the result of invoking + BOOST_PP_LOCAL_ITERATE, + which will ultimately be a file in the Preprocessor library + itself. You may find it surprising that many preprocessors can + handle repeated file inclusion more quickly than nested + horizontal repetition, but that is in fact the case.

+

If we throw the new example at our preprocessor, we'll see the + following, on three separate lines in the output:

+
template <> struct tiny_size< none , none , none > : mpl::int_<0>
+ {};
+
+template < class T0> struct tiny_size< T0 , none , none > : mpl::
+int_<1> {};
+
+template < class T0 , class T1> struct tiny_size< T0 , T1 , none
+> : mpl::int_<2> {};
+
+ +

That represents a great improvement in verifiability, but it's + still not ideal. As TINY_MAX_SIZE + grows, it gets harder and harder to see that the pattern is + generating what we'd like. If we could get some more line breaks + into the output it would retain a more recognizable form.

+

Both repetition methods we've used so far have another + drawback, though it doesn't show up in this example. Consider + what would happen if tiny_size + had a member function that we wanted to debug. If you've ever + tried to use a debugger to step through a function generated by + a preprocessor macro, you know that it's a frustrating + experience at best: The debugger shows you the line from which + the macro was ultimately invoked, which usually looks nothing at + all like the code that was generated. Worse, as far as the + debugger is concerned, every statement in that + generated function occupies that same line.

+
+
+

File Iteration

+

Clearly, debuggability depends on preserving the association + between generated code and the lines in the source file that + describe the code pattern. File iteration generates pattern + instances by repeatedly #include-ing + the same source file. The effect of file iteration on + debuggability is similar to that of templates: Although separate + instances appear to occupy the same source lines in the + debugger, we do have the experience of stepping through the + function's source code.

+

To apply file iteration in our example, we can replace our + earlier local iteration code and the definition of TINY_size, with:

+
#include <boost/preprocessor/iteration/iterate.hpp>
+#define BOOST_PP_ITERATION_LIMITS (0, TINY_MAX_SIZE - 1)
+#define BOOST_PP_FILENAME_1       "tiny_size_spec.hpp"
+#include BOOST_PP_ITERATE()
+
+

BOOST_PP_ITERATION_LIMITS + follows the same pattern as BOOST_PP_LOCAL_LIMITS did, allowing + us to specify an inclusive range of iteration indices. BOOST_PP_FILENAME_1 specifies the + name of the file to repeatedly #include (we'll show you that file + in a moment). The trailing 1 + indicates that this is the first nesting level of file + iteration—should we need to invoke file iteration again from + within tiny_size_spec.hpp, + we'd need to use BOOST_PP_FILENAME_2 + instead.

+

The contents of tiny_size_spec.hpp + should look familiar to you; most of it is the same as TINY_size's replacement-list, + without the backslashes:

+
#define n BOOST_PP_ITERATION()
+
+template <BOOST_PP_ENUM_PARAMS(n, class T)>
+struct tiny_size<
+    BOOST_PP_ENUM_PARAMS(n,T)
+    BOOST_PP_COMMA_IF(n)
+    BOOST_PP_ENUM(BOOST_PP_SUB(TINY_MAX_SIZE,n), TINY_print, none)
+>
+  : mpl::int_<n> {};
+
+#undef n
+
+ +

The Library transmits the iteration index to us in the result + of BOOST_PP_ITERATION(); + n is + nothing more than a convenient local macro used to reduce + syntactic noise. Note that we didn't use #include guards because we need tiny_size_spec.hpp + to be processed multiple times.

+

The preprocessed result should now preserve the line structure + of the pattern and be more verifiable for larger values of TINY_MAX_SIZE. + For instance, when TINY_MAX_SIZE + is 8, + the following excerpt appears in the output of GCC's + preprocessing phase:

+
...
+template < class T0 , class T1 , class T2 , class T3>
+struct tiny_size<
+    T0 , T1 , T2 , T3
+    ,
+    none , none , none , none
+>
+  : mpl::int_<4> {};
+
+template < class T0 , class T1 , class T2 , class T3 , class T4>
+struct tiny_size<
+    T0 , T1 , T2 , T3 , T4
+    ,
+    none , none , none
+>
+  : mpl::int_<5> {};
+...etc.
+
+ +
+
+

Self-Iteration

+

Creating an entirely new file like tiny_size_spec.hpp each time we want + to express a trivial code pattern for file repetition can be + inconvenient. Fortunately, the library provides a macro that + allows us to place the pattern right in the file that invokes + the iteration. BOOST_PP_IS_ITERATING + is defined to a nonzero value whenever we're inside an + iteration. We can use that value to select between the part of a + file that invokes the iteration and the part that provides the + repeated pattern. Here's a complete tiny_size.hpp file that demonstrates + self-iteration. Note in particular the placement and use of the + #include + guard TINY_SIZE_HPP_INCLUDED:

+
#ifndef BOOST_PP_IS_ITERATING
+
+#  ifndef TINY_SIZE_HPP_INCLUDED
+#    define TINY_SIZE_HPP_INCLUDED
+
+#    include <boost/preprocessor/repetition.hpp>
+#    include <boost/preprocessor/arithmetic/sub.hpp>
+#    include <boost/preprocessor/punctuation/comma_if.hpp>
+#    include <boost/preprocessor/iteration/iterate.hpp>
+
+#    ifndef TINY_MAX_SIZE
+#      define TINY_MAX_SIZE 3  // default maximum size is 3
+#    endif
+
+// primary template
+template <BOOST_PP_ENUM_PARAMS(TINY_MAX_SIZE, class T)>
+struct tiny_size
+  : mpl::int_<TINY_MAX_SIZE>
+{};
+
+// generate specializations
+#    define BOOST_PP_ITERATION_LIMITS (0, TINY_MAX_SIZE - 1)
+#    define BOOST_PP_FILENAME_1       "tiny_size.hpp" // this file
+#    include BOOST_PP_ITERATE()
+
+#  endif // TINY_SIZE_HPP_INCLUDED
+
+#else // BOOST_PP_IS_ITERATING
+
+#  define n BOOST_PP_ITERATION()
+
+#  define TINY_print(z, n, data) data
+
+// specialization pattern
+template <BOOST_PP_ENUM_PARAMS(n, class T)>
+struct tiny_size<
+    BOOST_PP_ENUM_PARAMS(n,T)
+    BOOST_PP_COMMA_IF(n)
+    BOOST_PP_ENUM(BOOST_PP_SUB(TINY_MAX_SIZE,n), TINY_print, none)
+>
+  : mpl::int_<n> {};
+
+#  undef TINY_print
+#  undef n
+
+#endif // BOOST_PP_IS_ITERATING
+
+
+
+

More

+

There's a good deal more to file iteration than what we've been + able to show you here. For more details, we encourage you to + delve into the library's electronic documentation of BOOST_PP_ITERATE and friends. Also, + it's important to note that no single technique for repetition + is superior to any other: Your choice may depend on convenience, + verifiability, debuggability, compilation speed, and your own + sense of "logical coherence."

+
+
+
+
+

A.4.2   Arithmetic, + Logical, and Comparison Operations

+

As we mentioned earlier, many of the Preprocessor library + interfaces require single-token numeric arguments, and when those + numbers need to be computed arithmetically, straightforward + arithmetic expressions are inappropriate. We used BOOST_PP_SUB to subtract two numeric + tokens in our tiny_size + examples. The library contains a suite of operations for + non-negative integral token arithmetic in its arithmetic/ subdirectory, as shown in + Table A.1

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preprocessor Library Arithmetic Operations
ExpressionValue of Single Token Result
BOOST_PP_ADD(x,y)x + y
BOOST_PP_DEC(x)x - 1
BOOST_PP_DIV(x,y)x / y
BOOST_PP_INC(x)x + 1
BOOST_PP_MOD(x,y)x % y
BOOST_PP_MUL(x,y)x * y
BOOST_PP_SUB(x,y)x - y
+

The logical/ + subdirectory contains the convenient Boolean token operations shown + in Table A.2 and the more efficient operations shown in Table A.3, + which require that their operands are either 0 or 1 (a single bit).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preprocessor Library Integer Logical Operations
ExpressionValue of Single Token Result
BOOST_PP_AND(x,y)x && y
BOOST_PP_NOR(x,y)!(x || y)
BOOST_PP_OR(x,y)x || y
BOOST_PP_XOR(x,y)(bool)x + != (bool)y   + ? 1 : 0
BOOST_PP_NOT(x)x ? 0 : + 1
BOOST_PP_BOOL(x)x ? 1 : + 0
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preprocessor Library Bit Logical Operations
ExpressionValue of Single Token Result
BOOST_PP_BITAND(x,y)x && y
BOOST_PP_BITNOR(x,y)!(x || y)
BOOST_PP_BITOR(x,y)x || y
BOOST_PP_BITXOR(x,y)(bool)x + != (bool)y   + ? 1 : 0
BOOST_PP_COMPL(x)x ? 0 : + 1
+

Finally, the comparison/ + subdirectory provides the token integral comparison operations shown + in Table A.4.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preprocessor Library Comparison Operations
ExpressionValue of Single Token Result
BOOST_PP_EQUAL(x,y)x == y   ? 1 : + 0
BOOST_PP_NOT_EQUAL(x,y)x != y   ? 1 : + 0
BOOST_PP_LESS(x,y)x < y    ? 1 : + 0
BOOST_PP_LESS_EQUAL(x,y)x <= y   ? 1 : + 0
BOOST_PP_GREATER(x,y)x > y    ? 1 : + 0
BOOST_PP_GREATER_EQUAL(x,y)x >= y   ? 1 : + 0
+

Because it's common to have a choice among several workable + comparison operators, it may be useful to know that BOOST_PP_EQUAL and BOOST_PP_NOT_EQUAL are likely to be O(1) + while the other comparison operators are generally slower.

+
+
+

A.4.3   Control Structures

+

In its control/ + directory, the Preprocessor Library supplies a macro BOOST_PP_IF(c,t,f) that fulfills a + similar role to the one filled by mpl::if_. To explore the "control" + group, we'll generate code for a framework of generic function + objects: the Boost Function Library.[8] boost::function is partially specialized + to match function type arguments of each arity up to the maximum + supported by the library:

+
template <class Signature> struct function;   // primary template
+
+template <class R>                                   // arity = 0
+struct function<R()>
+  definition not shown...
+
+template <class R, class A0>                         // arity = 1
+struct function<R(A0)>
+  definition not shown...
+
+template <class R, class A0, class A1>               // arity = 2
+struct function<R(A0,A1)>
+  definition not shown...
+
+template <class R, class A0, class A1, class A2>     // arity = 3
+struct function<R(A0,A1,A2)>
+  definition not shown...
+
+etc.
+
+ + + + + + + + + +
[8]We touched briefly on the design of Boost Function when we + discussed type erasure in Chapter 9. See the Function library + documentation at boost_1_32_0/libs/function/index.html + on the CD that accompanies this book for more information.
+

We've already covered a few strategies that can be used to generate + the pattern above, so we won't belabor that part of the problem; the + file iteration approach we used for tiny_size would be fine:

+
#ifndef BOOST_PP_IS_ITERATING
+
+#  ifndef BOOST_FUNCTION_HPP_INCLUDED
+#    define BOOST_FUNCTION_HPP_INCLUDED
+
+#    include <boost/preprocessor/repetition.hpp>
+#    include <boost/preprocessor/iteration/iterate.hpp>
+
+#    ifndef FUNCTION_MAX_ARITY
+#      define FUNCTION_MAX_ARITY 15
+#    endif
+
+template <class Signature> struct function;   // primary template
+
+// generate specializations
+#    define BOOST_PP_ITERATION_LIMITS (0, FUNCTION_MAX_ARITY)
+#    define BOOST_PP_FILENAME_1    "boost/function.hpp" // this file
+#    include BOOST_PP_ITERATE()
+
+#  endif // BOOST_FUNCTION_HPP_INCLUDED
+
+#else // BOOST_PP_IS_ITERATING
+
+#  define n BOOST_PP_ITERATION()
+
+// specialization pattern
+template <class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)>
+struct function<R ( BOOST_PP_ENUM_PARAMS(n,A) )>
+  definition not shown...
+
+#  undef n
+
+#endif // BOOST_PP_IS_ITERATING
+
+

BOOST_PP_ENUM_TRAILING_PARAMS, + used above, is just like BOOST_PP_ENUM_PARAMS + except that when its first argument is not 0, it generates a leading comma.

+ +
+

A.4.3.1   Argument Selection

+

For the sake of interoperability with C++ standard library + algorithms, it might be nice if functions of one or two arguments were + derived from appropriate specializations of std::unary_function or std::binary_function, respectively.[9] + BOOST_PP_IF + is a great tool for dealing with special cases:

+
#  include <boost/preprocessor/control/if.hpp>
+#  include <boost/preprocessor/comparison/equal.hpp>
+
+// specialization pattern
+template <class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)>
+struct function<R ( BOOST_PP_ENUM_PARAMS(n,A) )>
+  BOOST_PP_IF(
+      BOOST_PP_EQUAL(n,2), : std::binary_function<A0, A1, R>
+    , BOOST_PP_IF(
+          BOOST_PP_EQUAL(n,1), : std::unary_function<A0, R>
+        , ...empty argument...
+      )
+  )
+{ ...class body omitted... };
+
+ + + + + + + + + +
[9]While derivation from std::unary_function or std::binary_function might be + necessary for interoperability with some older library + implementations, it may inhibit the Empty Base Optimization + (EBO) from taking effect when two such derived classes are + part of the same object. For more information, see section + 9.4. In general, it's better to expose first_argument_type, second_argument_type, and result_type typedefs directly.
+

Well, our first attempt has run into several problems. First off, + you're not allowed to pass an empty argument to the preprocessor.[3] + Secondly, because angle brackets don't get special treatment, the + commas in the std::unary_function + and std::binary_function + specializations above are treated as macro argument separators, + and the preprocessor will complain that we've passed the wrong + number of arguments to BOOST_PP_IF + in two places.

+

Because it captures all of the issues, let's focus on the inner BOOST_PP_IF + invocation for a moment. The strategy that mpl::eval_if uses, of selecting a + nullary function to invoke, could work nicely here. The + preprocessor doesn't have a direct analogue for mpl::eval_if, but it doesn't really + need one: We can get the right effect by adding a second set of + parentheses to BOOST_PP_IF.

+
#define BOOST_FUNCTION_unary()    : std::unary_function<A0,R>
+#define BOOST_FUNCTION_empty()    // nothing
+
+...
+
+    , BOOST_PP_IF(
+          BOOST_PP_EQUAL(n,1), BOOST_FUNCTION_unary
+        , BOOST_FUNCTION_empty
+      )()
+
+#undef BOOST_FUNCTION_empty
+#undef BOOST_FUNCTION_unary
+
+ +

A nullary macro that generates nothing is so commonly needed that + the library's "facilities" group provides one: BOOST_PP_EMPTY. To complete the + example we'll need to delay evaluation all the way to the outer BOOST_PP_IF + invocation, because std::binary_function<A0,A1,R> + also has a "comma problem":

+
#  include <boost/preprocessor/facilities/empty.hpp>
+
+#  define BOOST_FUNCTION_binary() : std::binary_function<A0,A1,R>
+#  define BOOST_FUNCTION_unary()  : std::unary_function<A0,R>
+
+// specialization pattern
+template <class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)>
+struct function<R ( BOOST_PP_ENUM_PARAMS(n,A) )>
+  BOOST_PP_IF(
+      BOOST_PP_EQUAL(n,2), BOOST_FUNCTION_binary
+    , BOOST_PP_IF(
+          BOOST_PP_EQUAL(n,1), BOOST_FUNCTION_unary
+        , BOOST_PP_EMPTY
+      )
+  )()
+{ 
+    ...class body omitted...
+};
+
+#  undef BOOST_FUNCTION_unary
+#  undef BOOST_FUNCTION_binary
+#  undef n
+
+ +

Note that because we happened to be using file iteration, we + could have also used #if + on n's + value directly:

+
  template <class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)>
+  struct function<R ( BOOST_PP_ENUM_PARAMS(n,A) )>
+#if n == 2
+    : std::binary_function<A0, A1, R>
+#elif n == 1
+    : std::unary_function<A0, R>
+#endif
+
+ +

BOOST_PP_IF + has the advantage of enabling us to encapsulate the logic in a + reusable macro, parameterized on n, that is compatible with all + repetition constructs:

+
#define BOOST_FUNCTION_BASE(n)                                \
+    BOOST_PP_IF(BOOST_PP_EQUAL(n,2), BOOST_FUNCTION_binary    \
+      , BOOST_PP_IF(BOOST_PP_EQUAL(n,1), BOOST_FUNCTION_unary \
+           , BOOST_PP_EMPTY                                   \
+        )                                                     \
+    )()
+
+
+
+

A.4.3.2   Other Selection + Constructs

+

BOOST_PP_IDENTITY, + also in the "facilities" group, is an interesting cousin of BOOST_PP_EMPTY:

+
#define BOOST_PP_IDENTITY(tokens) tokens BOOST_PP_EMPTY
+
+ +

You can think of it as creating a nullary macro that returns tokens: + When empty parentheses are appended, the trailing BOOST_PP_EMPTY is expanded leaving + just tokens + behind. If we had wanted inheritance from mpl::empty_base when function's arity is not one or two, we + could have used BOOST_PP_IDENTITY:

+
// specialization pattern
+template <class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)>
+struct function<R ( BOOST_PP_ENUM_PARAMS(n,A) )>
+  BOOST_PP_IF(
+      BOOST_PP_EQUAL(n,2), BOOST_FUNCTION_binary
+    , BOOST_PP_IF(
+          BOOST_PP_EQUAL(n,1), BOOST_FUNCTION_unary
+        , BOOST_PP_IDENTITY(: mpl::empty_base)
+      )
+  )()
+{ 
+    ...class body omitted...
+};
+
+ +

It's also worth knowing about BOOST_PP_EXPR_IF, which generates its + second argument or nothing, depending on the Boolean value of its + first:

+
#define BOOST_PP_EXPR_IF(c,tokens)                           \
+   BOOST_PP_IF(c,BOOST_PP_IDENTITY(tokens),BOOST_PP_EMPTY)()
+
+ +

So BOOST_PP_EXPR_IF(1,foo) + expands to foo, + while BOOST_PP_EXPR_IF(0,foo) + expands to nothing.

+
+
+
+

A.4.4   Token Pasting

+

It would be nice if there were a generic way to access the return + and parameter types of all function objects, rather than + just the unary and binary ones. A metafunction returning the + signature as an MPL sequence would do the trick. We could just + specialize signature + for each function + arity:

+
template <class F> struct signature; // primary template
+
+// partial specializations for boost::function
+template <class R>
+struct signature<function<R()> > 
+  : mpl::vector1<R> {};
+
+template <class R, class A0>
+struct signature<function<R(A0)> > 
+  : mpl::vector2<R,A0> {};
+
+template <class R, class A0, class A1>
+struct signature<function<R(A0,A1)> > 
+  : mpl::vector3<R,A0,A1> {};
+
+...
+
+ +

To generate these specializations, we might add the following to + our pattern:

+
template <class R BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)>
+struct signature<function<R( BOOST_PP_ENUM_PARAMS(n,A) )> >
+  : mpl::BOOST_PP_CAT(vector,n)<
+      R BOOST_PP_ENUM_TRAILING_PARAMS(n,A)
+    > {};
+
+ +

BOOST_PP_CAT + implements token pasting; its two arguments are + "glued" together into a single token. Since this is a + general-purpose macro, it sits in cat.hpp at the top level of the + library's directory tree.

+

Although the preprocessor has a built-in token-pasting operator, ##, it only + works within a macro definition. If we'd used it here, it wouldn't + have taken effect at all:

+
template <class R>
+struct signature<function<R()> > 
+  : mpl::vector##1<R> {};
+
+template <class R, class A0>
+struct signature<function<R(A0)> > 
+  : mpl::vector##2<R,A0> {};
+
+template <class R, class A0, class A1>
+struct signature<function<R(A0,A1)> > 
+  : mpl::vector##3<R,A0,A1> {};
+
+...
+
+ +

Also, ## + often yields surprising results by taking effect before its + arguments have been expanded:

+
#define N           10
+#define VEC(i)      vector##i
+
+VEC(N)           // vectorN
+
+ +

By contrast, BOOST_PP_CAT + delays concatenation until after its arguments have been fully + evaluated:

+
#define N           10
+#define VEC(i)      BOOST_PP_CAT(vector,i)
+
+VEC(N)           // vector10
+
+ +
+
+

A.4.5   Data Types

+

The Preprocessor library also provides data types, + which you can think of as being analogous to the MPL's type + sequences. Preprocessor data types store macro arguments + instead of C++ types.

+
+

A.4.5.1   Sequences

+

A sequence (or seq for short) + is any string of nonempty parenthesized macro arguments. + For instance, here's a three-element sequence:

+
#define MY_SEQ   (f(12))(a + 1)(foo)
+
+ +

Here's how we might use a sequence to generate specializations of + the is_integral + template from the Boost Type Traits library (see Chapter 2):

+
#include <boost/preprocessor/seq.hpp>
+
+template <class T>
+struct is_integral : mpl::false_ {}; 
+
+// a seq of integral types with unsigned counterparts
+#define BOOST_TT_basic_ints            (char)(short)(int)(long)
+
+// generate a seq containing "signed t" and "unsigned t"
+#define BOOST_TT_int_pair(r,data,t)      (signed t)(unsigned t)
+
+// a seq of all the integral types
+#define BOOST_TT_ints                                           \
+    (bool)(char)                                                \
+    BOOST_PP_SEQ_FOR_EACH(BOOST_TT_int_pair, ~, BOOST_TT_basic_ints)
+
+// generate an is_integral specialization for type t
+#define BOOST_TT_is_integral_spec(r,data,t) \
+   template <>                              \
+   struct is_integral<t> : mpl::true_ {}; 
+
+BOOST_PP_SEQ_FOR_EACH(BOOST_TT_is_integral_spec, ~, BOOST_TT_ints)
+
+#undef BOOST_TT_is_integral_spec
+#undef BOOST_TT_ints
+#undef BOOST_TT_int_pair
+#undef BOOST_TT_basic_ints
+
+ +

BOOST_PP_SEQ_FOR_EACH + is a higher-order macro, similar to BOOST_PP_REPEAT, that invokes its + first argument on each element of its third argument.

+

Sequences are the most efficient, most flexible, and + easiest-to-use of the library's data structures, provided that you + never need to make an empty one: An empty sequence would contain + no tokens, and so couldn't be passed as a macro argument. The + other data structures covered here all have an empty + representation.

+

The facilities for manipulating sequences are all in the + library's seq/ + subdirectory. They are summarized in Table A.5, where t is the sequence (t0)(t1)...(tk). Where s, r, and + d appear, they have a similar purpose to the z parameters we discussed earlier (and + suggested you ignore for now).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preprocessor Sequence Operations
ExpressionResult
BOOST_PP_SEQ_CAT(t)t0t1...tk
BOOST_PP_SEQ_ELEM(n,t)tn
BOOST_PP_SEQ_ENUM(t)t0, t1, ...tk
BOOST_PP_SEQ_FILTER(pred,data,t)t + without the elements that don't satisfy pred
BOOST_PP_SEQ_FIRST_N(n,t)(t0)(t1)...(tn-1)
BOOST_PP_SEQ_FOLD_LEFT(op, + x, t)...op(s,op(s,op(s,x,t0),t1),t2)...
BOOST_PP_SEQ_FOLD_RIGHT(op, + x, t)...op(s,op(s,op(s,x,tk),tk-1), + tk-2)...
BOOST_PP_SEQ_FOR_EACH(f, + x, t)f(r, x,t0) f(r, x,t1)...f(r, x,tk)
BOOST_PP_SEQ_FOR_EACH_I(g, + x, t)g(r, x, 0, + t0) + g(r, x, 1, t1)... g(r, x, k, tk)
BOOST_PP_SEQ_FOR_EACH_PRODUCT(h, + x, t) +
+
Cartesian product—
+
see online docs
+
+
BOOST_PP_SEQ_INSERT(t,i,tokens)(t0)(t1)...(ti-1)(tokens) + (ti)(ti+1)...(tk)
BOOST_PP_SEQ_POP_BACK(t)(t0)(t1)...(tk-1)
BOOST_PP_SEQ_POP_FRONT(t)(t1)(t2)...(tk)
BOOST_PP_SEQ_PUSH_BACK(t,tokens)(t0)(t1)...(tk)(tokens)
BOOST_PP_SEQ_PUSH_FRONT(t,tokens)(tokens)(t0)(t1)...(tk)
BOOST_PP_SEQ_REMOVE(t,i)(t0)(t1)...(ti-1)(ti+1)...(tk)
BOOST_PP_SEQ_REPLACE(t,i,tokens)(t0)(t1)...(ti-1)(tokens)(ti+1)...(tk)
BOOST_PP_SEQ_REST_N(n,t)(tn)(tn+1)...(tk)
BOOST_PP_SEQ_REVERSE(t)(tk)(tk-1)...(t0)
BOOST_PP_SEQ_HEAD(t)t0
BOOST_PP_SEQ_TAIL(t)(t1)(t2)...(tk)
BOOST_PP_SEQ_SIZE(t)k+1
BOOST_PP_SEQ_SUBSEQ(t,i,m)(ti)(ti+1)...(ti+m-1)
BOOST_PP_SEQ_TO_ARRAY(t)(k+1 + ,(t0,t1,...tk))
BOOST_PP_SEQ_TO_TUPLE(t)(t0, t1,...tk)
BOOST_PP_SEQ_TRANSFORM(f, + x, t)(f(r,x,t0)) (f(r,x,t1))...(f(r,x,tk))
+

It's worth noting that while there is no upper limit on the + length of a sequence, operations such as BOOST_PP_SEQ_ELEM that take numeric + arguments will only work with values up to 256.

+
+
+

A.4.5.2   Tuples

+

A tuple is a very simple data structure for + which the library provides random access and a few other basic + operations. A tuple takes the form of a parenthesized, + comma-separated list of macro arguments. For example, + this is a three-element tuple:

+
#define TUPLE3     (f(12), a + 1, foo)
+
+

The operations in the library's tuple/ subdirectory can handle tuples + of up to 25 elements. For example, a tuple's Nth element can be accessed via BOOST_PP_TUPLE_ELEM, as follows:

+
                 // length  index  tuple 
+BOOST_PP_TUPLE_ELEM(   3   ,  1  , TUPLE3)   // a + 1
+
+ +

Notice that we had to pass the tuple's length as the second + argument to BOOST_PP_TUPLE_ELEM; + in fact, all tuple operations require explicit + specification of the tuple's length. We're not going to summarize + the other four operations in the "tuple" group here—you can + consult the Preprocessor library's electronic documentation for + more details. We note, however, that sequences can be transformed + into tuples with BOOST_PP_SEQ_TO_TUPLE, + and nonempty tuples can be transformed back into sequences with BOOST_PP_TUPLE_TO_SEQ.

+

The greatest strength of tuples is that they conveniently take + the same representation as a macro argument list:

+
#define FIRST_OF_THREE(a1,a2,a3)    a1
+#define SECOND_OF_THREE(a1,a2,a3)   a2
+#define THIRD_OF_THREE(a1,a2,a3)    a3
+
+// uses tuple as an argument list
+# define SELECT(selector, tuple)    selector tuple
+
+SELECT(THIRD_OF_THREE, TUPLE3)   // foo
+
+
+
+

A.4.5.3   Arrays

+

An array is just a tuple containing a + non-negative integer and a tuple of that length:

+
#define ARRAY3     ( 3, TUPLE3 )
+
+

Because an array carries its length around with it, the library's + interface for operating on arrays is much more convenient than the + one used for tuples:

+
BOOST_PP_ARRAY_ELEM(1, ARRAY3)     // a + 1
+
+ +

The facilities for manipulating arrays of up to 25 elements are + all in the library's array/ + subdirectory. They are summarized in Table A.6, where a is the array (k, (a0,a1,...ak-1)).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preprocessor Array Operations
ExpressionResult
BOOST_PP_ARRAY_DATA(a)(a0,a1,... + ak-1)
BOOST_PP_ARRAY_ELEM(i,a)ai
BOOST_PP_ARRAY_INSERT(a, + i, tokens)(k+1,(a0,a1,...ai-1, tokens, ai,ai+1,... + ak-1))
BOOST_PP_ARRAY_POP_BACK(a)(k-1,(a0,a1,... + ak-2))
BOOST_PP_ARRAY_POP_FRONT(a)(k-1,(a1,a2,... + ak-1))
BOOST_PP_ARRAY_PUSH_BACK(a, + tokens)(k+1,(a0,a1,... + ak-1, + tokens))
BOOST_PP_ARRAY_PUSH_FRONT(a, + tokens)(k+1,(tokens, + a1,a2,... + ak-1))
BOOST_PP_ARRAY_REMOVE(a, + i)(k-1,(a0,a1,... + ai-1,ai+1,... + ak-1))
BOOST_PP_ARRAY_REPLACE(a, + i, tokens)(k,(a0,a1,... + ai-1, + tokens, ai+1,... + ak-1))
BOOST_PP_ARRAY_REVERSE(a)(k,(ak-1,ak-2,... + a1,a0))
BOOST_PP_ARRAY_SIZE(a)k
+
+
+

A.4.5.4   Lists

+

A list is a two-element tuple whose first + element is the first element of the list, and whose second element + is a list of the remaining elements, or BOOST_PP_NIL if there are no remaining + elements. Lists have access characteristics similar to those of a + runtime linked list. Here is a three-element list:

+
#define LIST3     (f(12), (a + 1, (foo, BOOST_PP_NIL)))
+
+ +

The facilities for manipulating lists are all in the library's list/ + subdirectory. Because the operations are a subset of those + provided for sequences, we're not going to summarize them here—it + should be easy to understand the list operations by reading the + documentation on the basis of our coverage of sequences.

+

Like sequences, lists have no fixed upper length bound. Unlike + sequences, lists can also be empty. It's rare to need more than 25 + elements in a preprocessor data structure, and lists tend to be + slower to manipulate and harder to read than any of the other + structures, so they should normally be used only as a last resort.

+
+
+
+
+

A.5   Exercise

+
+
A-0
+
Fully preprocessor-ize the tiny + type sequence implemented in Chapter 5 so that all boilerplate code + is eliminated and the maximum size of a tiny sequence can be adjusted by + changing TINY_MAX_SIZE.
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/doc/contents.html b/doc/contents.html index b529517..8589eea 100644 --- a/doc/contents.html +++ b/doc/contents.html @@ -1,29 +1,38 @@ - - contents.html - - - - - -

Introduction

-

Topics

-

Terminology

-

Data Types

-

Reference

-

Headers

-

Examples

-

Miscellanea

- - - - - + + +

Introduction

+

Topics

+ + +

Terminology

+ + +

Data Types

+ + +

Reference

+ + +

Headers

+ + +

Examples

+ + +

Miscellanea

+ + + + diff --git a/doc/data/arrays.html b/doc/data/arrays.html index 181014e..d968c4f 100644 --- a/doc/data/arrays.html +++ b/doc/data/arrays.html @@ -1,5 +1,6 @@ + arrays.html @@ -17,12 +18,19 @@ size.  It only requires that an element exists at a certain index.
This allows macro parameters to be variable in size and allows data states to change size without the user explicitly keeping track of the - size independently.
+ size independently.
+
+ An array can be empty and have no elements. An empty array has a + 0 size. The notation for an empty array is '(0,())'.
+
+
With variadic macro support a tuple has all of the functionality as an array, knows its own size, and is easier syntactically to use. Because of that an array should be used, as opposed to a tuple, only if your compiler does not support - variadic macros.
+ variadic macros. The only advantage an array has over a tuple + is that an array can be empty while a tuple always + has at least one element and therefore can never have a size of 0.

Elements of an array can be extracted with BOOST_PP_ARRAY_ELEM, an array's size can be extracted with BOOST_PP_ARRAY_SIZE, diff --git a/doc/data/lists.html b/doc/data/lists.html index d7d99a3..27abf08 100644 --- a/doc/data/lists.html +++ b/doc/data/lists.html @@ -1,46 +1,42 @@ - - lists.html - - - -

Lists

-
- A list is a simple cons-style list with a head and a tail.  - The head of a list is an element, - and the tail is either another list or BOOST_PP_NIL. - For example, -
-
- (a, (b, (c, BOOST_PP_NIL))) -
-
- ...is a list of 3 elements--a, b, and c. -
-
- This allows macro parameters to be variable in size and allows data states to change - size without the user explicitly keeping track of the size independently. -
-
- Elements of a list can be extracted with - BOOST_PP_LIST_FIRST and BOOST_PP_LIST_REST.  -
-

Primitives

- -
-
- © Copyright Housemarque Oy 2002 -
© Copyright Paul Mensonides 2002 -
-
-

Distributed under the Boost Software License, Version 1.0. (See - accompanying file LICENSE_1_0.txt or - copy at www.boost.org/LICENSE_1_0.txt)

-
- + + + lists.html + + + +

Lists

+
A list is a simple cons-style list with a head and a + tail.  The head of a list is an element, and the tail is + either another list or BOOST_PP_NIL. For example,
+
(a, (b, (c, BOOST_PP_NIL))) +
+
...is a list of 3 elements--a, b, and c. +
+
This allows macro parameters to be variable in size and allows data + states to change size without the user explicitly keeping track of the + size independently.
+
+ A list can be empty and therefore have a size of 0. An empty list is + represented by the notation BOOST_PP_NIL.
+
+
+
Elements of a list can be extracted with BOOST_PP_LIST_FIRST + and BOOST_PP_LIST_REST
+

Primitives

+ +
+
© Copyright Housemarque Oy 2002
+ © Copyright Paul Mensonides 2002
+
+

Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt + or copy at www.boost.org/LICENSE_1_0.txt)

+
+ diff --git a/doc/data/sequences.html b/doc/data/sequences.html index e9286b3..746deb5 100644 --- a/doc/data/sequences.html +++ b/doc/data/sequences.html @@ -1,30 +1,23 @@ - - sequences.html - - - -

- Sequences -

-
- A sequence (abbreviated to seq) is a group of adjacent parenthesized elements. For example, -
-
- (a)(b)(c) -
-
- ...is a seq of 3 elements--a, b, and c. -
-
- Sequences are data structures that merge the properties of both lists and - tuples with the exception that a seq cannot be empty.  - Therefore, an "empty" seq is considered a special case scenario that - must be handled separately in C++. -
-
-
-#define SEQ (x)(y)(z)
+  
+    
+    sequences.html
+    
+  
+  
+    

Sequences

+
A sequence (abbreviated to seq) is a group of adjacent + parenthesized elements. For example,
+
(a)(b)(c)
+
...is a seq of 3 elements--a, b, and c. +
+
Sequences are data structures that merge the properties of + both lists and tuples with the exception that a seq, like + a tuple, cannot be empty.  Therefore, an "empty" seq + is considered a special case scenario that must be handled separately in + C++.
+
+
#define SEQ (x)(y)(z)
 #define REVERSE(s, state, elem) (elem) state
    // append to head                  ^
 
@@ -41,35 +34,27 @@ BOOST_PP_SEQ_FOLD_RIGHT(INC, BOOST_PP_SEQ_NIL, SEQ)
    //                        ^
    // special placeholder that will be "eaten"
    // by appending to the tail
-
-
-
- Sequences are extremely efficient.  Element access speed approaches - random access--even with seqs of up to 256 elements.  This - is because element access (among other things) is implemented iteratively - rather than recursively.  Therefore, elements can be accessed at extremely - high indices even on preprocessors with low maximum expansion depths. -
-
- Elements of a seq can be extracted with BOOST_PP_SEQ_ELEM. -
-

- Primitives -

- -
-
- © Copyright Housemarque Oy 2002 -
© Copyright Paul Mensonides 2002 -
-
-

Distributed under the Boost Software License, Version 1.0. (See - accompanying file LICENSE_1_0.txt or - copy at www.boost.org/LICENSE_1_0.txt)

-
- +
+
Sequences are extremely efficient.  Element access speed + approaches random access--even with seqs of up to 256 + elements.  This is because element access (among other things) is + implemented iteratively rather than recursively.  Therefore, elements + can be accessed at extremely high indices even on preprocessors with low + maximum expansion depths.
+
Elements of a seq can be extracted with BOOST_PP_SEQ_ELEM. +
+

Primitives

+ +
+
© Copyright Housemarque Oy 2002
+ © Copyright Paul Mensonides 2002
+
+

Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt + or copy at www.boost.org/LICENSE_1_0.txt)

+
+ diff --git a/doc/data/tuples.html b/doc/data/tuples.html index 4b5bbea..7a93c9b 100644 --- a/doc/data/tuples.html +++ b/doc/data/tuples.html @@ -1,5 +1,6 @@ + tuples.html @@ -9,13 +10,19 @@ parenthesis.  For example,
(a, b, c)
...is a tuple of 3 elements--a, b, and - c.
+ c.
+
+ A tuple cannot be empty. The notation '()' as a tuple is + a single element tuple of size 1, where the element is empty.
Tuples are fast and easy to use.  With variadic macro support it is not necessary to know the size of a tuple; without variadic macro support all access to tuples requires knowledge of its size. Use a tuple instead of an array if your compiler supports variadic macros, since a tuple has all of - the functionality as an array and is easier syntactically to use.
+ the functionality as an array and is easier syntactically to use. + The only functionality an array has which a tuple does + not have is that an array can be empty whereas a tuple cannot + be empty.
Elements of a tuple can be extracted with BOOST_PP_TUPLE_ELEM.

Primitives

diff --git a/doc/ref/limit_repeat.html b/doc/ref/limit_repeat.html index b813415..b31272d 100644 --- a/doc/ref/limit_repeat.html +++ b/doc/ref/limit_repeat.html @@ -1,34 +1,39 @@ - - BOOST_PP_LIMIT_REPEAT - - - -
- The BOOST_PP_LIMIT_REPEAT macro defines the maximum number of repetitions supported by each BOOST_PP_REPEAT dimension. -
-

Usage

-
- BOOST_PP_LIMIT_REPEAT -
-

Remarks

-
- This macro current expands to 256. -
-

Requirements

-
- Header:  <boost/preprocessor/config/limits.hpp> -
-
-
- © Copyright Housemarque Oy 2002 -
© Copyright Paul Mensonides 2002 -
-
-

Distributed under the Boost Software License, Version 1.0. (See - accompanying file LICENSE_1_0.txt or - copy at www.boost.org/LICENSE_1_0.txt)

-
- + + + BOOST_PP_LIMIT_REPEAT + + + +
The BOOST_PP_LIMIT_REPEAT macro + defines the maximum number of repetitions supported by each BOOST_PP_REPEAT + dimension.
+

Usage

+
BOOST_PP_LIMIT_REPEAT
+

Remarks

+
This macro current expands to 256.
+
+ NOTE: for the current latest versions of Microsoft's VC++ compiler there + is a nested macro limit of 256. This means in actuality that the number of + repetitions using VC++ is actually less than 256 depending on the + repetition macro being used. For the BOOST_PP_REPEAT macro this limit + appears to be 252 while for the BOOST_PP_ENUM... series of macros this + limit appears to be around 230, before the VC++ compiler gives a "C1009: + compiler limit : macros nested too deeply" error. This is a compiler + limitation of VC++ which may vary depending on the specific repetition + macro being used, and therefore is not a problem the preprocessor library + can solve.
+

Requirements

+
Header:  <boost/preprocessor/config/limits.hpp> +
+
+
© Copyright Housemarque Oy 2002
+ © Copyright Paul Mensonides 2002
+
+

Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt + or copy at www.boost.org/LICENSE_1_0.txt)

+
+ diff --git a/doc/ref/seq_rest_n.html b/doc/ref/seq_rest_n.html index 16a53df..808ef9b 100644 --- a/doc/ref/seq_rest_n.html +++ b/doc/ref/seq_rest_n.html @@ -1,67 +1,55 @@ - - BOOST_PP_SEQ_REST_N - - - -
- The BOOST_PP_SEQ_REST_N macro expands to a seq of all but the - first n elements of a seq. -
-

- Usage -

-
- BOOST_PP_SEQ_REST_N(n, seq) -
-

- Arguments -

-
-
n
-
- The number of elements to remove. -
-
seq
-
- The seq from which the elements are to be removed. -
-
-

- Remarks -

-
- This macro extracts n elements from the beginning of seq and - returns the remainder of seq as a new seq -
-

- See Also -

- -

- Requirements -

-
- Header:  <boost/preprocessor/seq/rest_n.hpp> -
-

- Sample Code -

-
-
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/first_n.hpp>
#include <boost/preprocessor/seq/rest_n.hpp>
#include <boost/preprocessor/seq/size.hpp>

#define NUMBERS \
(0)(1)(2)(3)(4)(5)(6)(7)(8)(9) \
(10)(11)(12)(13)(14)(15)(16)(17)(18)(19) \
(20)(21)(22)(23)(24)(25)(26)(27)(28)(29) \
(30)(31)(32)(33)(34)(35)(36)(37)(38)(39) \
(40)(41)(42)(43)(44)(45)(46)(47)(48)(49) \
(50)(51)(52)(53)(54)(55)(56)(57)(58)(59) \
(60)(61)(62)(63)(64)(65)(66)(67)(68)(69) \
(70)(71)(72)(73)(74)(75)(76)(77)(78)(79) \
(80)(81)(82)(83)(84)(85)(86)(87)(88)(89) \
(90)(91)(92)(93)(94)(95)(96)(97)(98)(99) \
(100)(101)(102)(103)(104)(105)(106)(107)(108)(109) \
(110)(111)(112)(113)(114)(115)(116)(117)(118)(119) \
(120)(121)(122)(123)(124)(125)(126)(127)(128)(129) \
(130)(131)(132)(133)(134)(135)(136)(137)(138)(139) \
(140)(141)(142)(143)(144)(145)(146)(147)(148)(149) \
(150)(151)(152)(153)(154)(155)(156)(157)(158)(159) \
(160)(161)(162)(163)(164)(165)(166)(167)(168)(169) \
(170)(171)(172)(173)(174)(175)(176)(177)(178)(179) \
(180)(181)(182)(183)(184)(185)(186)(187)(188)(189) \
(190)(191)(192)(193)(194)(195)(196)(197)(198)(199) \
(200)(201)(202)(203)(204)(205)(206)(207)(208)(209) \
(210)(211)(212)(213)(214)(215)(216)(217)(218)(219) \
(220)(221)(222)(223)(224)(225)(226)(227)(228)(229) \
(230)(231)(232)(233)(234)(235)(236)(237)(238)(239) \
(240)(241)(242)(243)(244)(245)(246)(247)(248)(249) \
(250)(251)(252)(253)(254)(255)(256) \
/**/

#define SUPER_ADD(x, y) BOOST_PP_SEQ_ELEM(y, BOOST_PP_SEQ_REST_N(x, NUMBERS))

SUPER_ADD(100, 100) // expands to 200

#define SUPER_SUB(x, y) \
BOOST_PP_SEQ_SIZE( \
BOOST_PP_SEQ_REST_N( \
BOOST_PP_INC(y), \
BOOST_PP_SEQ_FIRST_N( \
BOOST_PP_INC(x), NUMBERS \
) \
) \
) \
/**/

SUPER_SUB(67, 25) // expands to 42
-
-
-
- © Copyright Housemarque Oy 2002 -
© Copyright Paul Mensonides 2002 -
-
-

Distributed under the Boost Software License, Version 1.0. (See - accompanying file LICENSE_1_0.txt or - copy at www.boost.org/LICENSE_1_0.txt)

-
- + + + BOOST_PP_SEQ_REST_N + + + +
The BOOST_PP_SEQ_REST_N macro + expands to a seq of all but the first n elements of a seq. +
+

Usage

+
BOOST_PP_SEQ_REST_N(n, seq)
+

Arguments

+
+
n
+
The number of elements to remove.
+
seq
+
The seq from which the elements are to be removed.
+
+

Remarks

+
This macro extracts n elements from the beginning of seq + and returns the remainder of seq as a new seq.
+
+
It is undefined behavior if n is greater or equal to the size + of the seq.
+

See Also

+ +

Requirements

+
Header:  <boost/preprocessor/seq/rest_n.hpp> +
+

Sample Code

+
+
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/first_n.hpp>
#include <boost/preprocessor/seq/rest_n.hpp>
#include <boost/preprocessor/seq/size.hpp>

#define NUMBERS \
(0)(1)(2)(3)(4)(5)(6)(7)(8)(9) \
(10)(11)(12)(13)(14)(15)(16)(17)(18)(19) \
(20)(21)(22)(23)(24)(25)(26)(27)(28)(29) \
(30)(31)(32)(33)(34)(35)(36)(37)(38)(39) \
(40)(41)(42)(43)(44)(45)(46)(47)(48)(49) \
(50)(51)(52)(53)(54)(55)(56)(57)(58)(59) \
(60)(61)(62)(63)(64)(65)(66)(67)(68)(69) \
(70)(71)(72)(73)(74)(75)(76)(77)(78)(79) \
(80)(81)(82)(83)(84)(85)(86)(87)(88)(89) \
(90)(91)(92)(93)(94)(95)(96)(97)(98)(99) \
(100)(101)(102)(103)(104)(105)(106)(107)(108)(109) \
(110)(111)(112)(113)(114)(115)(116)(117)(118)(119) \
(120)(121)(122)(123)(124)(125)(126)(127)(128)(129) \
(130)(131)(132)(133)(134)(135)(136)(137)(138)(139) \
(140)(141)(142)(143)(144)(145)(146)(147)(148)(149) \
(150)(151)(152)(153)(154)(155)(156)(157)(158)(159) \
(160)(161)(162)(163)(164)(165)(166)(167)(168)(169) \
(170)(171)(172)(173)(174)(175)(176)(177)(178)(179) \
(180)(181)(182)(183)(184)(185)(186)(187)(188)(189) \
(190)(191)(192)(193)(194)(195)(196)(197)(198)(199) \
(200)(201)(202)(203)(204)(205)(206)(207)(208)(209) \
(210)(211)(212)(213)(214)(215)(216)(217)(218)(219) \
(220)(221)(222)(223)(224)(225)(226)(227)(228)(229) \
(230)(231)(232)(233)(234)(235)(236)(237)(238)(239) \
(240)(241)(242)(243)(244)(245)(246)(247)(248)(249) \
(250)(251)(252)(253)(254)(255)(256) \
/**/

#define SUPER_ADD(x, y) BOOST_PP_SEQ_ELEM(y, BOOST_PP_SEQ_REST_N(x, NUMBERS))

SUPER_ADD(100, 100) // expands to 200

#define SUPER_SUB(x, y) \
BOOST_PP_SEQ_SIZE( \
BOOST_PP_SEQ_REST_N( \
BOOST_PP_INC(y), \
BOOST_PP_SEQ_FIRST_N( \
BOOST_PP_INC(x), NUMBERS \
) \
) \
) \
/**/

SUPER_SUB(67, 25) // expands to 42
+
+
+
© Copyright Housemarque Oy 2002
+ © Copyright Paul Mensonides 2002
+
+

Distributed under the Boost Software License, Version 1.0. (See + accompanying file LICENSE_1_0.txt + or copy at www.boost.org/LICENSE_1_0.txt)

+
+ diff --git a/doc/title.html b/doc/title.html index 9d97712..fb2e101 100644 --- a/doc/title.html +++ b/doc/title.html @@ -1,5 +1,6 @@ + title.html @@ -11,15 +12,14 @@ may be used as a standalone library.
An excerpt from C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond by Dave Abrahams and Aleksey - Gurtovoy has been made available online. + Gurtovoy has been made available. This excerpt contains a basic introduction to the Preprocessor library and preprocessor metaprogramming which may help users new to the library and users interested in seeing some of the facilities offered by the library.
diff --git a/include/boost/preprocessor/arithmetic/dec.hpp b/include/boost/preprocessor/arithmetic/dec.hpp index 0503359..23dd0a3 100644 --- a/include/boost/preprocessor/arithmetic/dec.hpp +++ b/include/boost/preprocessor/arithmetic/dec.hpp @@ -284,5 +284,6 @@ # define BOOST_PP_DEC_254 253 # define BOOST_PP_DEC_255 254 # define BOOST_PP_DEC_256 255 +# define BOOST_PP_DEC_257 256 # # endif diff --git a/include/boost/preprocessor/config/config.hpp b/include/boost/preprocessor/config/config.hpp index fa5ca5b..835b283 100644 --- a/include/boost/preprocessor/config/config.hpp +++ b/include/boost/preprocessor/config/config.hpp @@ -70,16 +70,18 @@ # # /* BOOST_PP_VARIADICS */ # +# define BOOST_PP_VARIADICS_MSVC 0 # if !defined BOOST_PP_VARIADICS # /* variadic support explicitly disabled for all untested compilers */ -# if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC && !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI +# if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || ( defined __SUNPRO_CC && __SUNPRO_CC < 0x5130 ) || defined __HP_aCC && !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI # define BOOST_PP_VARIADICS 0 # /* VC++ (C/C++) */ # elif defined _MSC_VER && _MSC_VER >= 1400 && (!defined __EDG__ || defined(__INTELLISENSE__)) && !defined __clang__ # define BOOST_PP_VARIADICS 1 +# undef BOOST_PP_VARIADICS_MSVC # define BOOST_PP_VARIADICS_MSVC 1 # /* Wave (C/C++), GCC (C++) */ -# elif defined __WAVE__ && __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ +# elif defined __WAVE__ && __WAVE_HAS_VARIADICS__ || defined __GNUC__ && defined __GXX_EXPERIMENTAL_CXX0X__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1 # /* EDG-based (C/C++), GCC (C), and unknown (C/C++) */ # elif !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L @@ -91,6 +93,7 @@ # undef BOOST_PP_VARIADICS # define BOOST_PP_VARIADICS 1 # if defined _MSC_VER && _MSC_VER >= 1400 && (defined(__INTELLISENSE__) || !(defined __EDG__ || defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __clang__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI)) +# undef BOOST_PP_VARIADICS_MSVC # define BOOST_PP_VARIADICS_MSVC 1 # endif # else diff --git a/include/boost/preprocessor/library.hpp b/include/boost/preprocessor/library.hpp index aa5b777..3fb03d8 100644 --- a/include/boost/preprocessor/library.hpp +++ b/include/boost/preprocessor/library.hpp @@ -32,5 +32,6 @@ # include # include # include +# include # # endif diff --git a/include/boost/preprocessor/repetition/for.hpp b/include/boost/preprocessor/repetition/for.hpp index 5a63753..c38946b 100644 --- a/include/boost/preprocessor/repetition/for.hpp +++ b/include/boost/preprocessor/repetition/for.hpp @@ -16,6 +16,8 @@ # # include # include +# include +# include # include # # /* BOOST_PP_FOR */ @@ -42,7 +44,23 @@ # include # endif # -# define BOOST_PP_FOR_257(s, p, o, m) BOOST_PP_ERROR(0x0002) +# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC() +# define BOOST_PP_FOR_257_PR(s, p) BOOST_PP_BOOL(p##(257, s)) +# else +# define BOOST_PP_FOR_257_PR(s, p) BOOST_PP_BOOL(p(257, s)) +# endif + +# define BOOST_PP_FOR_257_ERROR() BOOST_PP_ERROR(0x0002) +# define BOOST_PP_FOR_257(s, p, o, m) \ + BOOST_PP_IIF \ + ( \ + BOOST_PP_FOR_257_PR(s,p), \ + BOOST_PP_FOR_257_ERROR, \ + BOOST_PP_EMPTY \ + ) \ + () \ +/**/ +// # define BOOST_PP_FOR_257(s, p, o, m) BOOST_PP_ERROR(0x0002) # # define BOOST_PP_FOR_CHECK_BOOST_PP_NIL 1 # diff --git a/include/boost/preprocessor/seq/detail/is_empty.hpp b/include/boost/preprocessor/seq/detail/is_empty.hpp new file mode 100644 index 0000000..1a80a2f --- /dev/null +++ b/include/boost/preprocessor/seq/detail/is_empty.hpp @@ -0,0 +1,49 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Edward Diener 2015. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_SEQ_DETAIL_IS_EMPTY_HPP +# define BOOST_PREPROCESSOR_SEQ_DETAIL_IS_EMPTY_HPP +# +# include +# include +# include +# include +# include +# +/* An empty seq is one that is just BOOST_PP_SEQ_NIL */ +# +# define BOOST_PP_SEQ_DETAIL_IS_EMPTY(seq) \ + BOOST_PP_COMPL \ + ( \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq) \ + ) \ +/**/ +# +# define BOOST_PP_SEQ_DETAIL_IS_EMPTY_SIZE(size) \ + BOOST_PP_COMPL \ + ( \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY_SIZE(size) \ + ) \ +/**/ +# +# define BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq) \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY_SIZE(BOOST_PP_SEQ_DETAIL_EMPTY_SIZE(seq)) \ +/**/ +# +# define BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY_SIZE(size) \ + BOOST_PP_BOOL(size) \ +/**/ +# +# define BOOST_PP_SEQ_DETAIL_EMPTY_SIZE(seq) \ + BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq (nil))) \ +/**/ +# +# endif diff --git a/include/boost/preprocessor/seq/for_each.hpp b/include/boost/preprocessor/seq/for_each.hpp index e997a9a..3f9c0d7 100644 --- a/include/boost/preprocessor/seq/for_each.hpp +++ b/include/boost/preprocessor/seq/for_each.hpp @@ -14,47 +14,94 @@ # # include # include +# include +# include # include # include # include +# include # include # include # # /* BOOST_PP_SEQ_FOR_EACH */ # # if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_SEQ_FOR_EACH(macro, data, seq) BOOST_PP_FOR((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) +# define BOOST_PP_SEQ_FOR_EACH(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK(macro, data, seq) # else # define BOOST_PP_SEQ_FOR_EACH(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_D(macro, data, seq) -# define BOOST_PP_SEQ_FOR_EACH_D(macro, data, seq) BOOST_PP_FOR((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) +# define BOOST_PP_SEQ_FOR_EACH_D(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK(macro, data, seq) # endif # -# define BOOST_PP_SEQ_FOR_EACH_P(r, x) BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(3, 2, x))) +# define BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC(macro, data, seq) BOOST_PP_FOR((macro, data, seq, BOOST_PP_SEQ_SIZE(seq)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) +# define BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY(macro, data, seq) +# +# define BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK(macro, data, seq) \ + BOOST_PP_IIF \ + ( \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq), \ + BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC, \ + BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY \ + ) \ + (macro, data, seq) \ +/**/ +# +# define BOOST_PP_SEQ_FOR_EACH_P(r, x) BOOST_PP_TUPLE_ELEM(4, 3, x) # # if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() # define BOOST_PP_SEQ_FOR_EACH_O(r, x) BOOST_PP_SEQ_FOR_EACH_O_I x # else -# define BOOST_PP_SEQ_FOR_EACH_O(r, x) BOOST_PP_SEQ_FOR_EACH_O_I(BOOST_PP_TUPLE_ELEM(3, 0, x), BOOST_PP_TUPLE_ELEM(3, 1, x), BOOST_PP_TUPLE_ELEM(3, 2, x)) +# define BOOST_PP_SEQ_FOR_EACH_O(r, x) BOOST_PP_SEQ_FOR_EACH_O_I(BOOST_PP_TUPLE_ELEM(4, 0, x), BOOST_PP_TUPLE_ELEM(4, 1, x), BOOST_PP_TUPLE_ELEM(4, 2, x), BOOST_PP_TUPLE_ELEM(4, 3, x)) # endif # -# define BOOST_PP_SEQ_FOR_EACH_O_I(macro, data, seq) (macro, data, BOOST_PP_SEQ_TAIL(seq)) +# define BOOST_PP_SEQ_FOR_EACH_O_I(macro, data, seq, sz) \ + BOOST_PP_SEQ_FOR_EACH_O_I_DEC(macro, data, seq, BOOST_PP_DEC(sz)) \ +/**/ +# define BOOST_PP_SEQ_FOR_EACH_O_I_DEC(macro, data, seq, sz) \ + ( \ + macro, \ + data, \ + BOOST_PP_IF \ + ( \ + sz, \ + BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, \ + BOOST_PP_SEQ_FOR_EACH_O_I_NIL \ + ) \ + (seq), \ + sz \ + ) \ +/**/ +# define BOOST_PP_SEQ_FOR_EACH_O_I_TAIL(seq) BOOST_PP_SEQ_TAIL(seq) +# define BOOST_PP_SEQ_FOR_EACH_O_I_NIL(seq) BOOST_PP_NIL # # if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -# define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_IM(r, BOOST_PP_TUPLE_REM_3 x) +# define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_IM(r, BOOST_PP_TUPLE_REM_4 x) # define BOOST_PP_SEQ_FOR_EACH_M_IM(r, im) BOOST_PP_SEQ_FOR_EACH_M_I(r, im) # else -# define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_I(r, BOOST_PP_TUPLE_ELEM(3, 0, x), BOOST_PP_TUPLE_ELEM(3, 1, x), BOOST_PP_TUPLE_ELEM(3, 2, x)) +# define BOOST_PP_SEQ_FOR_EACH_M(r, x) BOOST_PP_SEQ_FOR_EACH_M_I(r, BOOST_PP_TUPLE_ELEM(4, 0, x), BOOST_PP_TUPLE_ELEM(4, 1, x), BOOST_PP_TUPLE_ELEM(4, 2, x), BOOST_PP_TUPLE_ELEM(4, 3, x)) # endif # -# define BOOST_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq) macro(r, data, BOOST_PP_SEQ_HEAD(seq)) +# define BOOST_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq, sz) macro(r, data, BOOST_PP_SEQ_HEAD(seq)) # # /* BOOST_PP_SEQ_FOR_EACH_R */ # # if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_SEQ_FOR_EACH_R(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) +# define BOOST_PP_SEQ_FOR_EACH_R(r, macro, data, seq) BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_R(r, macro, data, seq) # else # define BOOST_PP_SEQ_FOR_EACH_R(r, macro, data, seq) BOOST_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) -# define BOOST_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq (nil)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) +# define BOOST_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_R(r, macro, data, seq) # endif # +# define BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC_R(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq, BOOST_PP_SEQ_SIZE(seq)), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M) +# define BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY_R(r, macro, data, seq) +# +# define BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_R(r, macro, data, seq) \ + BOOST_PP_IIF \ + ( \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq), \ + BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EXEC_R, \ + BOOST_PP_SEQ_FOR_EACH_DETAIL_CHECK_EMPTY_R \ + ) \ + (r, macro, data, seq) \ +/**/ +# # endif diff --git a/include/boost/preprocessor/seq/for_each_i.hpp b/include/boost/preprocessor/seq/for_each_i.hpp index c8edf5a..81028d7 100644 --- a/include/boost/preprocessor/seq/for_each_i.hpp +++ b/include/boost/preprocessor/seq/for_each_i.hpp @@ -15,47 +15,95 @@ # include # include # include +# include +# include # include # include # include +# include # include # include # # /* BOOST_PP_SEQ_FOR_EACH_I */ # # if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_SEQ_FOR_EACH_I(macro, data, seq) BOOST_PP_FOR((macro, data, seq (nil), 0), BOOST_PP_SEQ_FOR_EACH_I_P, BOOST_PP_SEQ_FOR_EACH_I_O, BOOST_PP_SEQ_FOR_EACH_I_M) +# define BOOST_PP_SEQ_FOR_EACH_I(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK(macro, data, seq) # else # define BOOST_PP_SEQ_FOR_EACH_I(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_I_I(macro, data, seq) -# define BOOST_PP_SEQ_FOR_EACH_I_I(macro, data, seq) BOOST_PP_FOR((macro, data, seq (nil), 0), BOOST_PP_SEQ_FOR_EACH_I_P, BOOST_PP_SEQ_FOR_EACH_I_O, BOOST_PP_SEQ_FOR_EACH_I_M) +# define BOOST_PP_SEQ_FOR_EACH_I_I(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK(macro, data, seq) # endif # -# define BOOST_PP_SEQ_FOR_EACH_I_P(r, x) BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(4, 2, x))) +# define BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK_EXEC(macro, data, seq) BOOST_PP_FOR((macro, data, seq, 0, BOOST_PP_SEQ_SIZE(seq)), BOOST_PP_SEQ_FOR_EACH_I_P, BOOST_PP_SEQ_FOR_EACH_I_O, BOOST_PP_SEQ_FOR_EACH_I_M) +# define BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK_EMPTY(macro, data, seq) +# +# define BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK(macro, data, seq) \ + BOOST_PP_IIF \ + ( \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq), \ + BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK_EXEC, \ + BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK_EMPTY \ + ) \ + (macro, data, seq) \ +/**/ +# +# define BOOST_PP_SEQ_FOR_EACH_I_P(r, x) BOOST_PP_TUPLE_ELEM(5, 4, x) # # if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() # define BOOST_PP_SEQ_FOR_EACH_I_O(r, x) BOOST_PP_SEQ_FOR_EACH_I_O_I x # else -# define BOOST_PP_SEQ_FOR_EACH_I_O(r, x) BOOST_PP_SEQ_FOR_EACH_I_O_I(BOOST_PP_TUPLE_ELEM(4, 0, x), BOOST_PP_TUPLE_ELEM(4, 1, x), BOOST_PP_TUPLE_ELEM(4, 2, x), BOOST_PP_TUPLE_ELEM(4, 3, x)) +# define BOOST_PP_SEQ_FOR_EACH_I_O(r, x) BOOST_PP_SEQ_FOR_EACH_I_O_I(BOOST_PP_TUPLE_ELEM(5, 0, x), BOOST_PP_TUPLE_ELEM(5, 1, x), BOOST_PP_TUPLE_ELEM(5, 2, x), BOOST_PP_TUPLE_ELEM(5, 3, x), BOOST_PP_TUPLE_ELEM(5, 4, x)) # endif # -# define BOOST_PP_SEQ_FOR_EACH_I_O_I(macro, data, seq, i) (macro, data, BOOST_PP_SEQ_TAIL(seq), BOOST_PP_INC(i)) +# define BOOST_PP_SEQ_FOR_EACH_I_O_I(macro, data, seq, i, sz) \ + BOOST_PP_SEQ_FOR_EACH_I_O_I_DEC(macro, data, seq, i, BOOST_PP_DEC(sz)) \ +/**/ +# define BOOST_PP_SEQ_FOR_EACH_I_O_I_DEC(macro, data, seq, i, sz) \ + ( \ + macro, \ + data, \ + BOOST_PP_IF \ + ( \ + sz, \ + BOOST_PP_SEQ_FOR_EACH_I_O_I_TAIL, \ + BOOST_PP_SEQ_FOR_EACH_I_O_I_NIL \ + ) \ + (seq), \ + BOOST_PP_INC(i), \ + sz \ + ) \ +/**/ +# define BOOST_PP_SEQ_FOR_EACH_I_O_I_TAIL(seq) BOOST_PP_SEQ_TAIL(seq) +# define BOOST_PP_SEQ_FOR_EACH_I_O_I_NIL(seq) BOOST_PP_NIL # # if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -# define BOOST_PP_SEQ_FOR_EACH_I_M(r, x) BOOST_PP_SEQ_FOR_EACH_I_M_IM(r, BOOST_PP_TUPLE_REM_4 x) +# define BOOST_PP_SEQ_FOR_EACH_I_M(r, x) BOOST_PP_SEQ_FOR_EACH_I_M_IM(r, BOOST_PP_TUPLE_REM_5 x) # define BOOST_PP_SEQ_FOR_EACH_I_M_IM(r, im) BOOST_PP_SEQ_FOR_EACH_I_M_I(r, im) # else -# define BOOST_PP_SEQ_FOR_EACH_I_M(r, x) BOOST_PP_SEQ_FOR_EACH_I_M_I(r, BOOST_PP_TUPLE_ELEM(4, 0, x), BOOST_PP_TUPLE_ELEM(4, 1, x), BOOST_PP_TUPLE_ELEM(4, 2, x), BOOST_PP_TUPLE_ELEM(4, 3, x)) +# define BOOST_PP_SEQ_FOR_EACH_I_M(r, x) BOOST_PP_SEQ_FOR_EACH_I_M_I(r, BOOST_PP_TUPLE_ELEM(5, 0, x), BOOST_PP_TUPLE_ELEM(5, 1, x), BOOST_PP_TUPLE_ELEM(5, 2, x), BOOST_PP_TUPLE_ELEM(5, 3, x), BOOST_PP_TUPLE_ELEM(5, 4, x)) # endif # -# define BOOST_PP_SEQ_FOR_EACH_I_M_I(r, macro, data, seq, i) macro(r, data, i, BOOST_PP_SEQ_HEAD(seq)) +# define BOOST_PP_SEQ_FOR_EACH_I_M_I(r, macro, data, seq, i, sz) macro(r, data, i, BOOST_PP_SEQ_HEAD(seq)) # # /* BOOST_PP_SEQ_FOR_EACH_I_R */ # # if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_SEQ_FOR_EACH_I_R(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq (nil), 0), BOOST_PP_SEQ_FOR_EACH_I_P, BOOST_PP_SEQ_FOR_EACH_I_O, BOOST_PP_SEQ_FOR_EACH_I_M) +# define BOOST_PP_SEQ_FOR_EACH_I_R(r, macro, data, seq) BOOST_PP_SEQ_FOR_EACH_I_R_DETAIL_CHECK(r, macro, data, seq) # else # define BOOST_PP_SEQ_FOR_EACH_I_R(r, macro, data, seq) BOOST_PP_SEQ_FOR_EACH_I_R_I(r, macro, data, seq) -# define BOOST_PP_SEQ_FOR_EACH_I_R_I(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq (nil), 0), BOOST_PP_SEQ_FOR_EACH_I_P, BOOST_PP_SEQ_FOR_EACH_I_O, BOOST_PP_SEQ_FOR_EACH_I_M) +# define BOOST_PP_SEQ_FOR_EACH_I_R_I(r, macro, data, seq) BOOST_PP_SEQ_FOR_EACH_I_R_DETAIL_CHECK(r, macro, data, seq) # endif # +# define BOOST_PP_SEQ_FOR_EACH_I_R_DETAIL_CHECK_EXEC(r, macro, data, seq) BOOST_PP_FOR_ ## r((macro, data, seq, 0, BOOST_PP_SEQ_SIZE(seq)), BOOST_PP_SEQ_FOR_EACH_I_P, BOOST_PP_SEQ_FOR_EACH_I_O, BOOST_PP_SEQ_FOR_EACH_I_M) +# define BOOST_PP_SEQ_FOR_EACH_I_R_DETAIL_CHECK_EMPTY(r, macro, data, seq) +# +# define BOOST_PP_SEQ_FOR_EACH_I_R_DETAIL_CHECK(r, macro, data, seq) \ + BOOST_PP_IIF \ + ( \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY(seq), \ + BOOST_PP_SEQ_FOR_EACH_I_R_DETAIL_CHECK_EXEC, \ + BOOST_PP_SEQ_FOR_EACH_I_R_DETAIL_CHECK_EMPTY \ + ) \ + (r, macro, data, seq) \ +/**/ +# # endif diff --git a/include/boost/preprocessor/seq/replace.hpp b/include/boost/preprocessor/seq/replace.hpp index d6107a7..0cf6b77 100644 --- a/include/boost/preprocessor/seq/replace.hpp +++ b/include/boost/preprocessor/seq/replace.hpp @@ -12,18 +12,34 @@ # ifndef BOOST_PREPROCESSOR_SEQ_REPLACE_HPP # define BOOST_PREPROCESSOR_SEQ_REPLACE_HPP # +# include # include # include +# include +# include # include # include +# include # # /* BOOST_PP_SEQ_REPLACE */ # # if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_SEQ_REPLACE(seq, i, elem) BOOST_PP_SEQ_FIRST_N(i, seq) (elem) BOOST_PP_SEQ_REST_N(BOOST_PP_INC(i), seq) +# define BOOST_PP_SEQ_REPLACE(seq, i, elem) BOOST_PP_SEQ_FIRST_N(i, seq) (elem) BOOST_PP_SEQ_REPLACE_DETAIL_REST(seq, i) # else # define BOOST_PP_SEQ_REPLACE(seq, i, elem) BOOST_PP_SEQ_REPLACE_I(seq, i, elem) -# define BOOST_PP_SEQ_REPLACE_I(seq, i, elem) BOOST_PP_SEQ_FIRST_N(i, seq) (elem) BOOST_PP_SEQ_REST_N(BOOST_PP_INC(i), seq) +# define BOOST_PP_SEQ_REPLACE_I(seq, i, elem) BOOST_PP_SEQ_FIRST_N(i, seq) (elem) BOOST_PP_SEQ_REPLACE_DETAIL_REST(seq, i) # endif # +# define BOOST_PP_SEQ_REPLACE_DETAIL_REST_EMPTY(seq, i) +# define BOOST_PP_SEQ_REPLACE_DETAIL_REST_VALID(seq, i) BOOST_PP_SEQ_REST_N(BOOST_PP_INC(i), seq) +# define BOOST_PP_SEQ_REPLACE_DETAIL_REST(seq, i) \ + BOOST_PP_IIF \ + ( \ + BOOST_PP_EQUAL(i,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq))), \ + BOOST_PP_SEQ_REPLACE_DETAIL_REST_EMPTY, \ + BOOST_PP_SEQ_REPLACE_DETAIL_REST_VALID \ + ) \ + (seq, i) \ +/**/ +# # endif diff --git a/include/boost/preprocessor/seq/rest_n.hpp b/include/boost/preprocessor/seq/rest_n.hpp index 6423376..5eea650 100644 --- a/include/boost/preprocessor/seq/rest_n.hpp +++ b/include/boost/preprocessor/seq/rest_n.hpp @@ -14,17 +14,32 @@ # # include # include +# include # include +# include +# include # include # include # # /* BOOST_PP_SEQ_REST_N */ # # if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_SEQ_REST_N(n, seq) BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_SEQ_SPLIT(BOOST_PP_INC(n), BOOST_PP_IDENTITY( (nil) seq )))() +# define BOOST_PP_SEQ_REST_N(n, seq) BOOST_PP_SEQ_REST_N_DETAIL_EXEC(n, seq, BOOST_PP_SEQ_DETAIL_EMPTY_SIZE(seq)) # else # define BOOST_PP_SEQ_REST_N(n, seq) BOOST_PP_SEQ_REST_N_I(n, seq) -# define BOOST_PP_SEQ_REST_N_I(n, seq) BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_SEQ_SPLIT(BOOST_PP_INC(n), BOOST_PP_IDENTITY( (nil) seq )))() +# define BOOST_PP_SEQ_REST_N_I(n, seq) BOOST_PP_SEQ_REST_N_DETAIL_EXEC(n, seq, BOOST_PP_SEQ_DETAIL_EMPTY_SIZE(seq)) # endif # +# define BOOST_PP_SEQ_REST_N_DETAIL_EXEC(n, seq, size) \ + BOOST_PP_EXPR_IIF \ + ( \ + BOOST_PP_BITAND \ + ( \ + BOOST_PP_SEQ_DETAIL_IS_NOT_EMPTY_SIZE(size), \ + BOOST_PP_NOT_EQUAL(n,size) \ + ), \ + BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_SEQ_SPLIT(BOOST_PP_INC(n), BOOST_PP_IDENTITY( (nil) seq )))() \ + ) \ +/**/ +# # endif diff --git a/include/boost/preprocessor/seq/size.hpp b/include/boost/preprocessor/seq/size.hpp index 385c00a..b5c8d9d 100644 --- a/include/boost/preprocessor/seq/size.hpp +++ b/include/boost/preprocessor/seq/size.hpp @@ -543,5 +543,6 @@ # define BOOST_PP_SEQ_SIZE_BOOST_PP_SEQ_SIZE_254 254 # define BOOST_PP_SEQ_SIZE_BOOST_PP_SEQ_SIZE_255 255 # define BOOST_PP_SEQ_SIZE_BOOST_PP_SEQ_SIZE_256 256 +# define BOOST_PP_SEQ_SIZE_BOOST_PP_SEQ_SIZE_257 257 # # endif diff --git a/test/facilities.cxx b/test/facilities.cxx index d824ce7..f81b6a0 100644 --- a/test/facilities.cxx +++ b/test/facilities.cxx @@ -36,7 +36,7 @@ BEGIN BOOST_PP_CAT(BOOST_PP_INTERCEPT, 2) 1 == 1 END #define OVMAC_3(x,y,z) BOOST_PP_ADD(BOOST_PP_MUL(x,y),z) #define OVMAC_4(x,y,z,a) BOOST_PP_ADD(BOOST_PP_MUL(x,y),BOOST_PP_MUL(a,z)) -#if defined(BOOST_PP_VARIADICS_MSVC) +#if BOOST_PP_VARIADICS_MSVC #define OVTEST(...) BOOST_PP_CAT(BOOST_PP_OVERLOAD(OVMAC_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY()) diff --git a/test/isempty.cxx b/test/isempty.cxx index d0c3776..56bc81b 100644 --- a/test/isempty.cxx +++ b/test/isempty.cxx @@ -38,7 +38,7 @@ #if BOOST_PP_VARIADICS -#if defined(BOOST_PP_VARIADICS_MSVC) /* Testing the VC++ variadic version */ +#if BOOST_PP_VARIADICS_MSVC /* Testing the VC++ variadic version */ /* INCORRECT */ diff --git a/test/isempty_variadic_standard_failure.cxx b/test/isempty_variadic_standard_failure.cxx index bfbbc9d..feee25f 100644 --- a/test/isempty_variadic_standard_failure.cxx +++ b/test/isempty_variadic_standard_failure.cxx @@ -12,7 +12,7 @@ # include # include -#if BOOST_PP_VARIADICS && (BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()) && !defined(BOOST_PP_VARIADICS_MSVC) +#if BOOST_PP_VARIADICS && (BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()) && !BOOST_PP_VARIADICS_MSVC #define FUNC_GEN8(x,y) (1,2,3) diff --git a/test/isempty_variadic_standard_failure2.cxx b/test/isempty_variadic_standard_failure2.cxx index d730626..f51d497 100644 --- a/test/isempty_variadic_standard_failure2.cxx +++ b/test/isempty_variadic_standard_failure2.cxx @@ -12,7 +12,7 @@ # include # include -#if BOOST_PP_VARIADICS && (BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()) && !defined(BOOST_PP_VARIADICS_MSVC) +#if BOOST_PP_VARIADICS && (BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()) && !BOOST_PP_VARIADICS_MSVC #define FUNC_GEN9(x,y,z) anything diff --git a/test/seq.cxx b/test/seq.cxx index bcda829..0ff7e66 100644 --- a/test/seq.cxx +++ b/test/seq.cxx @@ -12,12 +12,14 @@ # /* See http://www.boost.org for most recent version. */ # # include +# include # include # include # include # include # include # include +# include # include # include # include @@ -31,6 +33,50 @@ # define SEQ_NONE () # define SEQ (4)(1)(5)(2) + +# define SEQ_100 \ + (1)(2)(3)(4)(5)(6)(7)(8)(9) \ + (10)(11)(12)(13)(14)(15)(16)(17)(18)(19) \ + (20)(21)(22)(23)(24)(25)(26)(27)(28)(29) \ + (30)(31)(32)(33)(34)(35)(36)(37)(38)(39) \ + (40)(41)(42)(43)(44)(45)(46)(47)(48)(49) \ + (50)(51)(52)(53)(54)(55)(56)(57)(58)(59) \ + (60)(61)(62)(63)(64)(65)(66)(67)(68)(69) \ + (70)(71)(72)(73)(74)(75)(76)(77)(78)(79) \ + (80)(81)(82)(83)(84)(85)(86)(87)(88)(89) \ + (90)(91)(92)(93)(94)(95)(96)(97)(98)(99) \ + (100) + +# define SEQ_255 \ + (1)(2)(3)(4)(5)(6)(7)(8)(9) \ + (10)(11)(12)(13)(14)(15)(16)(17)(18)(19) \ + (20)(21)(22)(23)(24)(25)(26)(27)(28)(29) \ + (30)(31)(32)(33)(34)(35)(36)(37)(38)(39) \ + (40)(41)(42)(43)(44)(45)(46)(47)(48)(49) \ + (50)(51)(52)(53)(54)(55)(56)(57)(58)(59) \ + (60)(61)(62)(63)(64)(65)(66)(67)(68)(69) \ + (70)(71)(72)(73)(74)(75)(76)(77)(78)(79) \ + (80)(81)(82)(83)(84)(85)(86)(87)(88)(89) \ + (90)(91)(92)(93)(94)(95)(96)(97)(98)(99) \ + (100)(101)(102)(103)(104)(105)(106)(107)(108)(109) \ + (110)(111)(112)(113)(114)(115)(116)(117)(118)(119) \ + (120)(121)(122)(123)(124)(125)(126)(127)(128)(129) \ + (130)(131)(132)(133)(134)(135)(136)(137)(138)(139) \ + (140)(141)(142)(143)(144)(145)(146)(147)(148)(149) \ + (150)(151)(152)(153)(154)(155)(156)(157)(158)(159) \ + (160)(161)(162)(163)(164)(165)(166)(167)(168)(169) \ + (170)(171)(172)(173)(174)(175)(176)(177)(178)(179) \ + (180)(181)(182)(183)(184)(185)(186)(187)(188)(189) \ + (190)(191)(192)(193)(194)(195)(196)(197)(198)(199) \ + (200)(201)(202)(203)(204)(205)(206)(207)(208)(209) \ + (210)(211)(212)(213)(214)(215)(216)(217)(218)(219) \ + (220)(221)(222)(223)(224)(225)(226)(227)(228)(229) \ + (230)(231)(232)(233)(234)(235)(236)(237)(238)(239) \ + (240)(241)(242)(243)(244)(245)(246)(247)(248)(249) \ + (250)(251)(252)(253)(254)(255) + +# define SEQ_256 SEQ_255(256) + # define SEQVAR (4,5,8,3,61)(1,0)(5,22,43)(2)(17,45,33) # define REVERSAL(s, x, y) BOOST_PP_SUB(y, x) @@ -40,6 +86,8 @@ BEGIN BOOST_PP_IS_EMPTY(BOOST_PP_SEQ_HEAD(SEQ_NONE)) == 1 END BEGIN BOOST_PP_SEQ_HEAD(SEQ) == 4 END +BEGIN BOOST_PP_SEQ_HEAD(SEQ_255) == 1 END +BEGIN BOOST_PP_SEQ_HEAD(SEQ_256) == 1 END BEGIN BOOST_PP_SEQ_FOLD_LEFT(CAT_S, 1, SEQ_NONE) == 11 END BEGIN BOOST_PP_SEQ_FOLD_LEFT(SUB_S, 22, SEQ) == 10 END @@ -51,12 +99,21 @@ BEGIN BOOST_PP_IS_EMPTY(BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REVERSE(SEQ_NONE))) == 1 E BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REVERSE(SEQ)) == 2514 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REST_N(2, SEQ)) == 52 END +BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REST_N(99, SEQ_100)) == 100 END +BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REST_N(255, SEQ_256)) == 256 END BEGIN BOOST_PP_IS_EMPTY(BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_FIRST_N(1, SEQ_NONE))) == 1 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_FIRST_N(2, SEQ)) == 41 END +BEGIN BOOST_PP_SEQ_ELEM(50,BOOST_PP_SEQ_FIRST_N(100, SEQ_100)) == 51 END +BEGIN BOOST_PP_SEQ_ELEM(100,BOOST_PP_SEQ_FIRST_N(255, SEQ_255)) == 101 END +BEGIN BOOST_PP_SEQ_ELEM(200,BOOST_PP_SEQ_FIRST_N(256, SEQ_256)) == 201 END BEGIN BOOST_PP_IS_EMPTY(BOOST_PP_SEQ_ELEM(0, SEQ_NONE)) == 1 END BEGIN BOOST_PP_SEQ_SIZE(SEQ_NONE) == 1 END BEGIN BOOST_PP_SEQ_ELEM(2, SEQ) == 5 END +BEGIN BOOST_PP_SEQ_ELEM(20, SEQ_255) == 21 END +BEGIN BOOST_PP_SEQ_ELEM(254, SEQ_255) == 255 END +BEGIN BOOST_PP_SEQ_ELEM(220, SEQ_256) == 221 END +BEGIN BOOST_PP_SEQ_ELEM(255, SEQ_256) == 256 END BEGIN BOOST_PP_SEQ_SIZE(SEQ) == 4 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_TRANSFORM(CAT_S, 13, SEQ_NONE)) == 131 END @@ -83,29 +140,53 @@ BEGIN BOOST_PP_IS_EMPTY(BOOST_PP_ARRAY_ELEM(0, BOOST_PP_SEQ_TO_ARRAY(SEQ_NONE))) BEGIN BOOST_PP_ARRAY_SIZE(BOOST_PP_SEQ_TO_ARRAY(SEQ_NONE)) == 1 END # define LESS_S(s, x, y) BOOST_PP_LESS(x, y) +# define FILTER_MOD_S(s, data, elem) BOOST_PP_NOT(BOOST_PP_MOD(elem,data)) BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_FILTER(LESS_S, 3, SEQ)) == 45 END +BEGIN BOOST_PP_SEQ_ELEM(4,BOOST_PP_SEQ_FILTER(FILTER_MOD_S, 20, SEQ_100)) == 100 END +BEGIN BOOST_PP_SEQ_ELEM(2,BOOST_PP_SEQ_FILTER(FILTER_MOD_S, 30, SEQ_100)) == 90 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_INSERT(SEQ_NONE, 0, 7)) == 7 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_INSERT(SEQ, 0, 3)) == 34152 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_INSERT(SEQ, 2, 3)) == 41352 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_INSERT(SEQ, 4, 3)) == 41523 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_INSERT(SEQ_255, 0, 100)) == 256 END +BEGIN BOOST_PP_SEQ_ELEM(255,BOOST_PP_SEQ_INSERT(SEQ_255, 0, 100)) == 255 END +BEGIN BOOST_PP_SEQ_ELEM(0,BOOST_PP_SEQ_INSERT(SEQ_255, 0, 113)) == 113 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_POP_BACK(SEQ)) == 415 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_POP_BACK(SEQ_256)) == 255 END +BEGIN BOOST_PP_SEQ_ELEM(254,BOOST_PP_SEQ_POP_BACK(SEQ_256)) == 255 END +BEGIN BOOST_PP_SEQ_ELEM(100,BOOST_PP_SEQ_POP_BACK(SEQ_256)) == 101 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_POP_FRONT(SEQ)) == 152 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_POP_FRONT(SEQ_256)) == 255 END +BEGIN BOOST_PP_SEQ_ELEM(0,BOOST_PP_SEQ_POP_FRONT(SEQ_256)) == 2 END +BEGIN BOOST_PP_SEQ_ELEM(254,BOOST_PP_SEQ_POP_FRONT(SEQ_256)) == 256 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_PUSH_FRONT(SEQ_NONE, 145)) == 145 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_PUSH_FRONT(SEQ, 3)) == 34152 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_PUSH_FRONT(SEQ_255, 57)) == 256 END +BEGIN BOOST_PP_SEQ_ELEM(0,BOOST_PP_SEQ_PUSH_FRONT(SEQ_255, 222)) == 222 END +BEGIN BOOST_PP_SEQ_ELEM(255,BOOST_PP_SEQ_PUSH_FRONT(SEQ_255, 111)) == 255 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_PUSH_BACK(SEQ_NONE, 79)) == 79 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_PUSH_BACK(SEQ, 3)) == 41523 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_PUSH_BACK(SEQ_255, 199)) == 256 END +BEGIN BOOST_PP_SEQ_ELEM(254,BOOST_PP_SEQ_PUSH_BACK(SEQ_255, 99)) == 255 END +BEGIN BOOST_PP_SEQ_ELEM(255,BOOST_PP_SEQ_PUSH_BACK(SEQ_255, 99)) == 99 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REMOVE(SEQ, 0)) == 152 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REMOVE(SEQ, 2)) == 412 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REMOVE(SEQ, 3)) == 415 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_REMOVE(SEQ_255, 254)) == 254 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_REMOVE(SEQ_256, 255)) == 255 END + BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REPLACE(SEQ_NONE, 0, 22)) == 22 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REPLACE(SEQ, 0, 3)) == 3152 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REPLACE(SEQ, 1, 3)) == 4352 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_REPLACE(SEQ, 3, 3)) == 4153 END +BEGIN BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_REPLACE(SEQ_256, 255, 22)) == 256 END +BEGIN BOOST_PP_SEQ_ELEM(233,BOOST_PP_SEQ_REPLACE(SEQ_256, 255, 22)) == 234 END +BEGIN BOOST_PP_SEQ_ELEM(255,BOOST_PP_SEQ_REPLACE(SEQ_256, 255, 22)) == 22 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_SUBSEQ(SEQ, 0, 4)) == 4152 END BEGIN BOOST_PP_SEQ_CAT(BOOST_PP_SEQ_SUBSEQ(SEQ, 0, 2)) == 41 END