RE: [boost] Re: Problem with type_with_alignment.hpp
> [mailto:[EMAIL PROTECTED] On Behalf Of Daniel Frey > Exactly. But the expanded > is the result of the > preprocessor, so IIRC the two >'s are treated as two tokens, > not as one, > because they weren't glued together with ##. Also, the GCC > preprocessor > expands the above to > > < some_class<...> > > > and I'm pretty sure that the rules for inserting spaces are exactly > defined and there is not much room for interpretation. If the GCC is > correct to insert spaces, then the patch is a work-around for > a compiler > (here: preprocessor) bug. So, what is the correct behaviour here? It isn't technically supposed to insert spaces, but it is supposed to treat them as two consecutive tokens with no whitespace separation--same as "+-". You can get this situation similar to the following: #define MACRO(a) a> MACRO(>) The result is: '>' '>' Not: '>' ' ' '>' And definitely not: '>>' E.g. they are distinct, but a preprocessor shouldn't be adding whitespace *unless* it is producing a text stream which is going to be re-tokenized by a separate preprocessor/compiler pass. In that case, it *must* add the whitespace to prevent retokenization that yields different tokens. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] [Fun] (( a xor b )) formal review request...
> #define xor )?BOOST_DETAIL_XOR( FYI, you cannot legally define "xor" because it is specifically *not* an identifier--even to the preprocessor. This is the primary difference between "keywords" and textual "alternative tokens." 2.5/2 - "In all respects of the language, each alternative token behaves the same, respectively, as its primary token, except for its spelling." E.g. "#define ^" is invalid, and therefore "#define xor" is invalid. 16.1/4 (note #137) - "An alternative token (2.5) is not an identifier, even when its spelling consists entirely of letters and underscores. Therefore it is not subject to this replacement." Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Re: Files of types *.ipp are unfriendly, especiallytoMSVC ?
Paul A. Bristow wrote: > Since I couldn't find how to make the editor work with .ipp > files from the MS documentation, but it ws kindly provided by > a diligent Booster, can you suggest where this info shold be stored? FYI, a while back I got a "power toy" called vstweak that allows you to tweak stuff like this: http://www.gotdotnet.com/team/ide/ Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Fun PP lib example
Aleksey Gurtovoy wrote: > David Abrahams wrote: > > Here's an example I just cooked up of using the PP lib to solve a > > classic C++ OO problem: repeated boilerplate in the definition of > > Pimpl classes. > > There is another variation of the idiom, sometimes called > "hidden state", which doesn't have the shortcoming in the first place: Dave, do you still think this would be a good example to add to the docs? Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] PP interest in facilities for variablelengthargumentlists
> #define IS_END(...) IS_END_I(__VA_ARGS__,) > #define IS_END_I(x, ...) \ > IS_VARIADIC(IS_END_II x,) \ ^^^ > /**/ > #define IS_END_II(a, b, c, d, e, f, g, h, i, j, ...) __VA_ARGS__ Sorry, mistake. You need a bunch of commas here rather than just one. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] PP interest in facilities for variablelengthargumentlists
> -Original Message- > From: [EMAIL PROTECTED] > > it doesn't directly support variadics as a data structure. The > > reasons for this are simple: 1) Variadic data can contain > open commas > > and that interferes with parameter lists if you need to pass around > > more than one structure or if you need to use the variadic argument > > for something else. > > Very true, but in the common case you just have 1 variadic > list. In the remaining cases you must require the extra > parenthisis. For the implementation I posted, that only > occurs within internal library calls, and the extra > parenthisis are not required in the interface. The common case is variadic auxiliary data as in FILTER, TRANSFORM, REPEAT, FOR_EACH, etc.. The other common case is variadic state as in constructs such as FOR, WHILE, FOLD_LEFT, FOLD_RIGHT, etc.. If you use the variadic parameter to store your data type that you are processing, that means that you cannot have variadic auxiliary data or variadic state. I'll give you a small example. If I was to implement addition: // WHILE(pred, op, state) #define ADD(x, y) \ TUPLE_ELEM( \ 2, 0, \ WHILE(ADD_P, ADD_O, (x, y)) \ ) \ /**/ #define ADD_P(d, xy) TUPLE_ELEM(2, 1, xy) #define ADD_O(d, xy) \ ( INC(TUPLE_ELEM(2, 0, xy)), DEC(TUPLE_ELEM(2, 1, xy)) ) /**/ // WHILE(pred, op, ...) #define ADD(x, y) \ VARIADIC_ELEM( \ 0, WHILE(ADD_P, ADD_O, x, y) \ ) \ /**/ #define ADD_P(d, x, y) y #define ADD_O(d, x, y) INC(x), DEC(y) That's an example of how much cleaner and more efficient it is with variadic state. The same applies to auxiliary data also: #define BETWEEN(list, x, y) \ FILTER(BETWEEN_P, list, x, y) \ /**/ #define BETWEEN_P(d, elem, x, y) \ BITAND( LESS_EQUAL(x, elem), LESS_EQUAL(elem, y) ) \ /**/ The point is this: it is *far* more useful to allow variadic auxiliary data or state than it is half-support a data type that consistents of pure variadic data. The framework is there in Chaos to define such things fairly easily. They just won't match anything else in the library. There is no such framework in the pp-lib, however. > It seems to me that "empty" is a close enough approximation > to "end of the parameters," in practice. Here is an > implementation of IS_EMPTY that I don't think relies on any > undefined behavior. With two caveats: Empty is a valid element. It is not an approximation of "end of parameters". So, first, you can't use that a rogue value. Instead, you have to use something much more pathological. > 1) it cannot differenciate between foo(a,) and foo(a) where foo is: > > #define foo(x, ...) BOOST_PP_VA_IS_EMPTY(__VA_ARGS__) Invoking 'foo' without two arguments is undefined. You can't do this: foo(x) // error gcc allows this, but it is invalid. You *must* invoke it with the comma: foo(x,) > > 2) it causes most compilers to spit out a warning if the > final parameter ends in the name of a function-like macro. e.g.: > > foo(a, BOOST_PP_CAT) /* causes a warning message */ This is the point. You cannot pass certain types of data. There is *no way* to implement IS_EMPTY generally. Trust me, I've implemented it a hundred different ways. You must always restrict some sort of input. I.e. no function-like macros, no operators, etc.. Period. Likewise, you cannot detect the size of a variadic parameter without restricting the size of the variadic parameter. To further emphasize my point: Wave is an extremely strict preprocessor that won't preprocess your code. The code is not legal. If you want to detect whether or not you're "at-the-end", limit the size of the variadic parameters to (for example) 10 and do this: #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ #define SPLIT(i, ...) PRIMITIVE_CAT(SPLIT_, i)(__VA_ARGS__) #define SPLIT_0(a, ...) a #define SPLIT_1(a, ...) __VA_ARGS__ #define IS_VARIADIC(...) \ SPLIT(0, CAT(IS_VARIADIC_R_, IS_VARIADIC_C __VA_ARGS__)) \ /**/ #define IS_VARIADIC_C(...) 1 #define IS_VARIADIC_R_1 1, #define IS_VARIADIC_R_IS_VARIADIC_C 0, #define END (,,()) #define IS_END(...) IS_END_I(__VA_ARGS__,) #define IS_END_I(x, ...) \ IS_VARIADIC(IS_END_II x,) \ /**/ #define IS_END_II(a, b, c, d, e, f, g, h, i, j, ...) __VA_ARGS__ IS_END( a, b, c, d, END ) IS_END( END ) You can expand the END value to hundreds of commas and change IS_END_II likewise. That, or similar pathological input, is the only way that you can do this without undefined behavior in the absence of well-defined token-pasting. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] PP interest in facilities for variable lengthargumentlists
> > Not to the Boost library version. At least, not until > variadics and > > placemarkers are part of C++. > > But variadics are a part of C. Though this is a bit outside > of Boost's mission, the PP lib is arguably even more useful > to C programmers than it is to C++ programmers. I don't see > any harm in targeting C programmers for this particular > library, since they could be an important user base; as long > as it doesn't compromise the library's usefulness for C++ programmers. It isn't that it isn't worthwhile to support them. Rather, it is because there are already about three (on average) different implementations of the pp-lib to work around various (sometimes serious) compiler deficiencies. Supporting variadics and placemarkers from C99 would add, at minimum, two more versions of about half the library. That's why I don't want to support a "variadic" mode in general in the pp-lib at this point. However, that isn't why I don't want to add support for variadic parameters as a data type. (I'll address that below in more detail.) > > OTOH, the Chaos version of the library, which is nearly > complete, has > > full support for variadics and placemarkers from the ground up. > > I'm looking forward to your release of Chaos. Maybe this > exercise is just a learning experience for me, if you already > have implemented better variadic support in Chaos. Chaos is implemented from the ground up to support variadics. However, it doesn't directly support variadics as a data structure. The reasons for this are simple: 1) Variadic data can contain open commas and that interferes with parameter lists if you need to pass around more than one structure or if you need to use the variadic argument for something else. 2) There is no way (without resorting to undefined behavior) of detecting whether you're at the end of the variadic parameters. There are only two reasonable ways to do it: First, make an "end" rogue value that is pathological but detectable as opposed to any other possible input. 3) There is no such thing as a "nil" variadic parameter. There is *always* at least one parameter, though that parameter might be empty (a.k.a. "placemarker"), and second, limit the number of variadic parameters. Altogether, these issues make dealing with variadics as a data structure not worthwhile when you can just wrap the elements in parentheses and call it a "tuple." (BTW, even tuples are only supported up to a fixed size in Chaos because of the "end-of-data" issues mentioned above.) Support for variadics in Chaos, as far as algorithms are concerned, is to allow the data/state to be variadic. This is far more useful in practice, as it gets rid of a massive about of "element access" from one structure or another. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] PP interest in facilities for variable lengthargumentlists
> Can you elaborate some more on this. Do you mean that when a > library macro calls some user-defined macro, which in turn > calls the same library macro, then it will fail to evaluate? Yes. Macros are not allowed to recurse. This means that something like this: #define true false #define false true true // expands to "false", then expands to "true", then stops false // expands to "true", then expands to "false", then stops The problem, relative to library primitives that invoke user-defined macros, is that a simple macro of the form WHILE(pred, op, state) prohibits the use of WHILE when WHILE invokes the predicate and operation macros that are supplied by the user. What the pp-lib does is define a large set of WHILE macros (e.g.) all implemented similarly. It then defines "WHILE" as an object-like macro that expands to the next "available" (i.e. not disabled) WHILE macro. So the expression: WHILE(pred, op, state) Is actually the invocation of an object-like macro (WHILE) that expands to some available WHILE_xxx function-like macro which is invoked against the parameters. > I have to admit that I don't grok the magic BOOST_PP uses to > make recursion work. Could the same technique be used here > without duplicating a lot of code from the library? No. First, you'd have to define a large set of macros for several of the constructs that call user-defined macros (256 in the pp-lib). Second, you'd have to define a new library state for that construct (or make it act like another which requires changing other parts of the library). Third, you'd have to double the number of macros required to do the automatic recursion on buggy preprocessors. Fourth, you'd have to double number of implementation macros for EDG-based preprocessors to make it perform at any kind of reasonable speed. That is about what it would take to make "some" of the structures work. Some of the pp-lib's algorithms don't allow recursion because of this explosion in the number of macros. In Chaos, OTOH, recursion is abstracted and everything that takes user-defined macros/lambda expressions is reentrant (i.e. recursive). Under the Chaos model, defining algorithms that operate like you mention above is pretty easy. Each one would require about three or four macros, each one would be reentrant, and each one would be overloaded on lambda expression vs. user-defined macro. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] PP interest in facilities for variable length argumentlists
> The nice thing about the implementation is that it is layered > on-top of the existing BOOST_PP _ macros like BOOST_PP_WHILE. > So it doesn't require modifications to the existing library, > and none of the definitions are more that a few lines long. > All the functions live in the namespace BOOST_PP_VA_. A bit more on this part, the problem with implementing an algorithm on top of another algorithm like you do in your code, is that it makes the algorithm incapable of recursing in contexts where the algorithm calls some user-defined macro, such as a predicate or operation. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] PP interest in facilities for variable length argumentlists
> Is there interest in adding support for variable length > argument lists to the preprocessor library. Not to the Boost library version. At least, not until variadics and placemarkers are part of C++. OTOH, the Chaos version of the library, which is nearly complete, has full support for variadics and placemarkers from the ground up. > Variable length argument lists can be used in place of all > the existing data structures (i.e lists, sequences, tuples, > and arrays). I've put together a complete set of operations > on variable length argument lists, including iteration, > folds, transform, etc. 1) The Chaos library implements all algorithms generically, so there is no need to provide a specialized construct for a specific type of data unless is drastically more efficient to do so. 2) Variadic parameters are actually quite bad for use as a data structure. Specifically, the lack the iterative nature of sequences in certain contexts, the streamable capabilities of purely recursive structure like lists, and multiple "structures" cannot be passed to the same macro. Given variadics, a better structure is a plain tuple, (__VA_ARGS__). 3) Without well-defined token-pasting, there is no universally sound way of detecting the last element of a variadic structure. It is simply impossible. The best you can do is either restrict input or use some type of pathologically unlikely but detectable "end" value. Detection, on something that pathological, is expensive. One other alternative is to limit the size of the variadic data. If you do that, than you can recursively convert each element to any value you want, and the postfix a different value to indicate the end. Of course, if the limit is high, that is again expensive. Nevertheless, I'll take a look at your code... Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Draft of new Boost Software License
> My preference is for there to be a single license file in the > boost root > directory, and each file covered include a link. So a source > code file > might contain something like: > > // (C) Jane Programmer, 2003 > // > // See www.boost.org/license for license terms and conditions > // > // See www.boost.org/libs/janes-lib for documentation > > I'm not sure everyone agrees with that approach - part of the > reason for > discussion is to finalize that. I agree. Repetition in source code is, at best, annoying. Even if it is only in a license comment and not the code itself. Having the license in the file itself also... [sorry, sent too soon] ...makes the text subject to tools like "find" and "replace" which can alter copyright and is undetectable by the compilation process. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Draft of new Boost Software License
> My preference is for there to be a single license file in the > boost root > directory, and each file covered include a link. So a source > code file > might contain something like: > > // (C) Jane Programmer, 2003 > // > // See www.boost.org/license for license terms and conditions > // > // See www.boost.org/libs/janes-lib for documentation > > I'm not sure everyone agrees with that approach - part of the > reason for > discussion is to finalize that. I agree. Repetition in source code is, at best, annoying. Even if it is only in a license comment and not the code itself. Having the license in the file itself also ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Draft of new Boost Software License
> * Boost developers; if there are aspects of the license that make you > hesitate about adopting it, what are the issues? It looks fine to me Beman. Is this license (once it is completely ironed out) supposed to go in each file? If so, where do you put the credentials for who created what? Or do we leave that out altogether? Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Re: [ANN] New Version of theWavepreprocessorlibraryreleased (Isthis a bug?)
> This was my understanding too, which is why I claimed that my > wave executable might be buggy. Does your wave executable > also puke on the above snippet - if it does not, then i think > my wave's behavior may be an artifact of my "dirty" fix to > get the code to compile by declaring a primary template in > order to make the explicit specialization of "policy..." > well-formed. I have not studied the source code for wave yet > - and before (or if) i do, i was hoping if someone could > confirm or deny experiencing the same behavior with their > wave executable. > > regards, > Faisal Vali My executable does the same thing, so it is indeed a bug. I'm sure Hartmut will fix this shortly. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
RE: [boost] Re: [ANN] New Version of the Wavepreprocessorlibraryreleased (Isthis a bug?)
> -Original Message- > Well i did manage to get it to compile by simply adding a > primary template declaration for the policy class. > > It seemed to be behaving all right until i tried to > preprocess the following (and i wonder if i caused this > behavior by my above tinkering or whether this is truly > standard behavior): > > > #define C C > > #if C > X() > #endif > > Wave spits out that this is an ill-formed preprocessor expression - The expression of an #if (or #elif) directive should get four passes. The first pass handles the defined operator. Each instance of defined XYZ and defined(XYZ) is replaced with 0 or 1. The second pass does macro expansion. For the expression above, macro expansion results in C. The third pass converts all remaining identifier tokens, with the exception of true and false, with 0. (Note that that alternative tokens are not identifiers, so this doesn't apply to them.) Finally, yielding the expression 0. The fourth pass finally evaluates the expression, which should evaluate to false. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: ENFORCE
Gennaro Prota wrote: > Just that Borland won't warn on BOOST_INVARIANT(false). Admittedly > not a big one :-) This warning can be configured away simply by purposely accessing a non-constant variable or calling an inline function: inline bool force_non_constant() { return true; } if (force_non_constant(), expr) else ... Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] ATTN: All Developers Interested in Boost.Preprocessor
- Original Message - From: "Vesa Karvonen" <[EMAIL PROTECTED]> > The basic idea is that the keywords '__l_paren__', '__r_paren__' and > '__comma__' could be used in place of '(', ')' and ',', respectively. The > above example would now become: > > #define ID(x) x > ID( __l_paren__ ) > ID( a __comma__ b ) > ID( __r_paren__ ) > > and it would expand into: > >__l_paren__ a __comma__ b __r_paren__ I like the idea. (Though I'd prefer __lparen__ and __rparen__.) What about __hash__ and __hashhash__? It is currently illegal for # to appear in a function-like macro replacement list unless it leads a parameter. In which case, it is the stringizing operator. So, instead you have to do this... #define HASH() HASH_I #define HASH_I # #define HASH_HASH CAT(HASH(), HASH()) ...in order to produce the tokens # and ##. Commas and parentheses are much more of a problem though, I agree. Also, and perhaps more importantly than any of these "punctuation" operators: __newline__ ...which would have no effect on compilation but would insert newlines into preprocessing output. One question Vesa, what happens here: #define STRINGIZE(x) PRIMITIVE_STRINGIZE(x) #define PRIMITIVE_STRINGIZE(x) #x STRINGIZE(__comma__) // ? PRIMITIVE_STRINGIZE(__comma__) // ? I'm assuming that, because they aren't macros, they should not "expand" before stringizing. Finally, if C++ gets C99's inline _Pragma. Some standard pragmas could be used to generate these tokens: _Pragma("STDC TOKEN ,") Which could be shortened at will to: #define COMMA _Pragma("STDC TOKEN ,") Thoughts? Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] PP: MSVC BOOST_PP_REPEAT + BOOST_PP_SEQ_ELEM bug
Aleksey Gurtovoy wrote: > Paul Mensonides wrote: >>> Yep, they do - that's why I named it "BOOST_PP_REPEAT + >>> BOOST_PP_SEQ_ELEM bug". >> >> That is what I figured, but I wanted to make sure that the (a, b, c) >> wasn't causing a problem--which it shouldn't be anyway. I'll look >> at this later when I have time to install VC6 on my other computer. > > That would be much appreciated. Okay, this is "fixed," but before you update, this is the reduction of the problem. First, it has nothing to do with BOOST_PP_REPEAT per se. Rather it is the kind of instability that I mentioned before relative to IS_UNARY, since SEQ_ELEM does a similar kind of thing. Take a look: #include #define X() ... #define A(seq) BOOST_PP_SEQ_ELEM(0, seq) #define B(seq) (BOOST_PP_SEQ_ELEM(0, seq)) #define C(seq) ID( BOOST_PP_SEQ_ELEM(0, seq) ) #define D(seq) ID(( BOOST_PP_SEQ_ELEM(0, seq) )) #define ID(x) x A( (X)(Y) ) // X B( (X)(Y) ) // (X) C( (X)(Y) ) // X D( (X)(Y) ) // 0 The last one is wrong. It should expand to (X). This should be fixed now, but it illustrates the kind of encapsulation issues that I was referring to before. As far as the other bug is concerned, here is the reduction of the problem: // entire file... #define M() M VC6 expects to find the open parentheses of a macro invocation, but instead it finds EOF. There is nothing that I can do to fix this one. However, VC7 seems to have fixed this problem, at least. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Passing template-ids as macro parameters
Terje Slettebø wrote: >> MACRO( IN(2, (std::pair)) ) > > I'm not sure how this latter solution could be used. How could MACRO > retrieve the type being passed? You have to encode the type in a structure, and then decode it when you actually need it: #define IN(s, x) (s) x #define OUT(type) BOOST_PP_TUPLE_REM type #define MACRO(z, i, type) \ BOOST_PP_CAT(class T, i) = OUT(type) \ /**/ template< BOOST_PP_ENUM( 3, MACRO, IN(2, (std::pair)) ) > class xyz; Passing in an intermediate value like this: #define ID2(a, b) a, b #define MACRO(x) x MACRO( ID2( std::pair ) ) ...is error prone (and dangerous). :( Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Passing template-ids as macro parameters
Terje Slettebø wrote: > Is there some way (using PP-lib, or whatever), to pass a template-id > with more than one parameter (thus, it contains at least one comma), > to a macro? > > E.g.: > > #define TEST(a) test t; > > TEST(std::pair) // Won't work > > Maybe some sort of variation of BOOST_PP_IDENTITY: > > #define BOOST_PP_IDENTITY1(a) a > #define BOOST_PP_IDENTITY2(a,b) a,b > #define BOOST_PP_IDENTITY3(a,b,c) a,b,c > > etc. > > TEST(BOOST_PP_IDENTITY2(std::pair)) // Now ok I'll answer all three of these emails at once, since they are about the same thing. First, the above will cause problems, specifically problems like this: #define T1(a) T2(a) #define T2(a) test t; #define IDENTITY2(a, b) a, b T1(IDENTITY2(std::pair)) // error I.e. by the time that T2 is invoked, IDENTITY2 has already expanded, which yields too many arguments to T2. What we need is a general solution and a set of conventions for passing types. This is difficult without variadics to do with the preprocessor itself. Specifically, you have to use the core language: template struct wrap { typedef T type; }; template struct wrap { typedef T type; }; #define TYPE(x) wrap::type TYPE((int)) // okay TYPE((std::pair)) // okay However, this has its own problems. Specifically, it is using function types to store the type--which is inside parentheses and therefore protected from the preprocessor. The use of function types with cause certain things to error: TYPE(( void )) // error TYPE(( int (int, int) )) // function type altered to pointer-to-function TYPE(( int[2] )) // array altered to pointer There is only one other language construct that might be of use here: pointers-to-members. Specifically, it is parenthesized, yet does not undergo promotion/alteration when used in a parameter list. However, it is intrusive: template struct wrap; template struct wrap { typedef T type; }; #define TYPE(x) wrap::type TYPE(( std::pair::* )) ^^^ Also, this cannot be used for non-class types--which can still have commas in them: template struct typelist { typedef T head; typedef U tail; }; TYPE(( typelist::head::* )) // error So, without variadic macros, there is no "good" solution. Instead, you have to resort to hacks that require you to know the number of unbound commas in the type: #define IN(s, x) (s) x #define OUT(x) BOOST_PP_TUPLE_REM x #define M1(type) M2(type) #define M2(type) OUT(type) MACRO( IN(2, (std::pair)) ) In other words, it is a complete pain to deal with them without variadics. *With* variadics, however, you can do a little better. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] PP lambda?
Joel de Guzman wrote: > Looks good. But why not overload the name "namespace" in as much > as the CPP overloads #if #else ? I think the syntax should give a nice > feeling since it is already looks like something C++ programmers are > already accustomed to: > Either way, any syntax will do as long as it works :) If you really > want to go the import/export route, consider a modula-2-ish syntax: I actual names of the directives I don't really care about. #region/#endreg, #scope/#endscope, #module/#endmodule are all fine with me. I don't personally like #namespace/#endnamespace, but I could live with it. What I want (and what we need) is the more general mechanism allowing named scopes. My proposal, including import/export, would allow both the current model and the more general model. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] PP lambda?
Joel de Guzman wrote: > Hmmm how about namespaces (or modules) ? :o)... > > #< BOOST_PP // boost PP namespace > // blah blah blah > #> > > #< MY_MODULE // my module namespace > #using BOOST_PP // using boost PP namespace > // blah blah blah > #> Hi Joel, I'm already in the process of writing a paper with an alternative version of the above. Problem #1: the operator directives are evil. They are not visible, and with serve to make code that includes them hard to read. We need a named alternative at least. Problem #2: No true scoping is achieved: #< #define DETAIL 123 #define INTERFACE DETAIL #export INTERFACE #> INTERFACE // ? This is what I'm going to propose: # region // unnamed #import ABC #define XYZ #define INTERFACE 123 #export INTERFACE # endreg XYZ // XYZ INTERFACE // 123 # region BOOST #region DETAIL #define ABC 123 #endreg #define INTERFACE BOOST::DETAIL::ABC #define OTHER 123 #export OTHER #region A #define MACRO 123 #endref #region B #define MACRO 123 #endif #export A # endreg ABC // ABC DETAIL::ABC // DETAIL::ABC BOOST::INTERFACE // 123 OTHER// 123 A::MACRO // 123 B::MACRO // B::MACRO What do you think? Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Preprocessor documentation erratum
John Harris (TT) wrote: > In the 1.30.0 release, the docs for BOOST_PP_IF and BOOST_PP_IIF > incorrectly refer to 'expr'. It looks as though they were copied > from EXPR_IIF. > > john harris > trading technologies Thanks John, I'll fix it. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] [Bug] boost does not compile with Sun CC
> CC -DHAVE_CONFIG_H -I. -I. -I../../../../src -I../../../../boost > -I/usr/local/include -I/usr/openwin/include -I/usr/local/include -c > cregex.cpp "../../../../boost/boost/type_traits/add_const.hpp", line > 34: Warning: Too few arguments in macro BOOST_PP_CHECK_2. > "../../../../boost/boost/type_traits/add_const.hpp", line 34: > Warning: Too few arguments in macro BOOST_PP_CHECK_2. > "../../../../boost/boost/type_traits/add_const.hpp", line 34: > Warning: Too few arguments in macro BOOST_PP_CHECK_2. > "../../../../boost/boost/type_traits/add_const.hpp", line 34: Error: > BOOST_PP_LIST_FOR_EACH_I_M is not defined. > [...lots more] > > This message on the boost mail list seems to indicate that some fixes > may be available > <http://lists.boost.org/MailArchives/boost/msg41995.php>. Lars Gullik Bjønnes wrote: >> We just got this message on the LyX bug-tracker. >> >> This is from the RC_1_30_0 branch, is there any fixed planned for >> 1.30.0 proper? Are you certain that this is 1.30? This should already be fixed. In particular, the Sun preprocessor should be using the Borland configuration of the pp-lib--which should not be using the BOOST_PP_CHECK macros--especially not for list handling. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] ANN: Wave - A Standard conformant C++ preprocessor (was:IntheSpirit of Challenge)
Hartmut Kaiser wrote: > At the first steps it is not planned to make a very high performance > or > very small C++ preprocessor. If you are looking for these objectives > you probably have to look at other places. Please note that the EDG preprocessor will outperform the Wave preprocessor in simple cases. However, as complexity increases, time dilates expontentially on EDG. Preprocessing time dilates linearly under Wave, which causes it to easily outperform EDG when complexity increases. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] IBM preprocessor bugs (was Re: Borland C++ Builder patch4 released)
Markus Schöpflin wrote: > Paul, > > I recently reported the preprocessor bug that keeps BOOST_PP_EXPAND() > from working to IBM. > > The example you gave here is preprocessed correctly by the Visual Age > preprocessor for both version 5 and 6. I don't have any version of Visual Age, so I've never been able to test on it. What I know, from other people testing things for me, is that Borland configuration works okay on IBM's preprocessor. The Borland configuration of the pp-lib only works around one thing: placing the name of a function-like macro in front of something that isn't a parameter list. In particular something that is either textual or numeric, such as the example that I sent earlier. So, I'm not exactly sure what the problem is. I suppose you could try preprocessing the regression tests in the strict configuration of the pp-lib as well as the examples in the reference section of the docs. In any case, it might be the same type of thing as Borland, but only in certain context. I can't test it, though, so I can't tell you for sure. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Borland C++ Builder patch 4 released
Russell Hind wrote: > Sorry to say that the output is now incorrect. A2 instead of A 2. > Checking the preprocessor output for this gives > > /* Unit1.cpp 9: */int main() { > /* Unit1.cpp 10: */std::cout << "A 2" << &std::endl; > /* Unit1.cpp 11: */return 0; > > which is again correct. This is strange since I thought that bcc32 > was > just supposed to call cpp32 for the pre-processing. I can submit this > as a bug to Borlands QualityCentral if you like (but don't hold your > breath). :( I'm not surprised, but I was hoping If they fixed this bug, Borland would be able to use the "strict" configuration of the pp-lib. I'd still need the same hacked configuration for Sun and IBM (they have similar bugs), but at least Borland's wouldn't need it. Please do submit a bug report. I think they've already gotten this one before though, so I'm not holding my breath. ;) Thanks again for the help, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Borland C++ Builder patch 4 released
Russell Hind wrote: >> #define A() 1 >> #define B(m) m 2 >> >> B(A) >> > > I've run the above through the preprocessor and heres the output > > /* Unit1.cpp 1: */ > /* Unit1.cpp 2: */ > /* Unit1.cpp 3: */ > /* Unit1.cpp 4: */A 2 > > Tested using the preprocess option with BCB6Pro Update 4. This looks > like what you were hoping for. If you'd like me to test anything else > then just let me know. Thanks Russell. What happens if you compile it all the way, i.e. with a compileable example: #include #define A() 1 #define B(m) m 2 #define STR(x) STR_D(x) #define STR_D(x) #x int main() { std::cout << STR(B(A)) << &std::endl; return 0; } When this program is executed, it should output "A 2", not "A2". The reason that I ask is that the only thing I have is the free command line tools. The included preprocessor, cpp32.exe, produces the correct output. The compiler proper, bcc32.exe, does not. In other words, the behavior is/was different with the separate preprocessor vs. the "integrated" preprocessor. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Borland C++ Builder patch 4 released
Beman Dawes wrote: > Pavel, > > >Official patch 4 was released just now: > > > >http://bdn.borland.com/article/0,1410,29793,00.html > > > > > >Among bugs fixed is: > >- The bcc compiler now compiles code containing a const member > function. > > Hum... Interesting... Thanks for letting me know. Could some one that has this compiler please test something for me? I'm hoping that a preprocessor bug got fixed (though it isn't listed). #define A() 1 #define B(m) m 2 B(A) It should expand to "A 2", but will probably expand to "A2". Thanks in advance, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] on operator T* for array access
- Original Message - From: "Dave Abrahams" <[EMAIL PROTECTED]> > It just occurred to me that this trick only works when the underlying > pointer type is a real pointer. In other words, if smart_ptr is to be able > to provide array access, while wrapping arbitrary pointer-like types, an > operator[] is still required. Yes, you're right. My point was mostly that array support (equivalent to the default C++ array support) can be provided with only those two things--custom deallocator and implicit conversion to pointed-to type. Everything else is just a safety issue regarding polymorphic objects and arrays and isn't explicitly necessary. However, on a more general policy-based smart pointer front, it is a good idea for any policy at all to be able to disable a certain interface function (or ctor). This is fairly easy to encapsulate but is dependent on how the policies are passed into the smart pointer template (i.e. through one parameter as a typelist (or similar) or through multiple parameters with defaults or through multiple parameters with arbitrary ordering). Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: is_class
Peter Dimov wrote: (Hi, Peter. I'm merging two different posts on this subject and replying to both simultaneously.) >>> Yes, exactly. Apologies for the confusion. It is a common mistake to >>> provide only R T::* and expect that to match all pointers to >>> members. To get back to your earlier post, >>> >>> int (X::*pf) () const; >>> >>> is not the same as >>> >>> typedef int (*F) () const; > > Should be typedef int F() const; > >>> since the first typedef is ill-formed, function types cannot be >>> cv-qualified. > > That's 9.3/9, and yes, you are right, the typedef is legal. Yes an no. The typedef is ill-formed, but not directly because of the cv-qualification. To be technically accurate here, you cannot form a regular pointer (or reference) to a cv-qualified function type. It is prohibited. I.e. typedef int F() const; // legal typedef int (*F)() const; // illegal typedef int (&F)() const; // illegal > I learn > something new every day. Even though 3.9.3/1 implies that functions > cannot > be cv-qualified, and 8.3.5/4 says that creating a cv-qualified > function type makes the program ill-formed, R T::* still matches a > const member function, creating a const qualified function type as R. > Or so Comeau says. C++ sure moves in mysterious ways. Comeau is correct here. I'll spend a few words to clarify the subject though. Normal cv-qualification is compounded from some other type, as in "const T." In the case of function types however, cv-qualification is not compounded. It is inherently part of the base function type or it isn't. So, from a certain point-of-view, the above is accurate. You cannot take a function type and cv-qualify it. However, the function type itself might already be cv-qualified. In other words, cv-qualification on functions is not normal cv-qualification. Specifically, it refers to the cv-qualification of the implicit this pointer. E.g. something like this pseudo code: typedef void f() const; ...roughly equivalent (in pseudocode) to this: typedef void f(const class* this); ...which is why certain limitations exist on cv-qualified function types. Specifically, they can only be used in three ways: 1) to declare a non-static member function 2) to declare the pointed-to type of a pointer-to-member, and 3) to declare another typedef. Note that in the first two cases (i.e. the cases of actual use), the pseudo-type 'class' in the above can be deduced, either from the enclosing class or from the pointer-to-member class type. Any other use is illegal--such as forming a regular pointer or reference to a cv-qualified function type. Then second case is interesting in the particular case of detecting pointers-to-member-functions. The following is all legal: typedef void F() const; struct X { F f; }; void X::f() const { } F X::* pf = &X::f; By the same token, the function type 'F' can be extracted from a pointer-to-member-function with the specialization "R X::*" with 'R' being the original function type: #include template struct is_same { enum { value = false }; }; template struct is_same { enum { value = true }; }; template struct extract; template struct extract { enum { value = is_same::value }; }; int main() { std::cout << extract::value // 1 << &std::endl; return 0; } Just for the record, however, Comeau doesn't get this whole area right (and many other compilers don't get it right at all). Comeau doesn't consider the type extracted from a pointer-to-member-function to be a regular function type. Rather, it considers it to be some type of psuedo-function-type ala "member function type"--which is incorrect. An example demonstrates this: #include #include typedef void F(); struct X { }; typedef F X::* PMF; template struct extract; template struct extract { typedef R type; }; extract::type f; // decl: no error void f() { return; } // def: error int main() { std::cout << typeid(f).name() // compiler crash // i.e. not an ICE << &std::endl; return 0; } I've been talking about this issue with Daveed Vandevoorde for the last couple weeks, so EDG is aware of the issue. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Array support[wasSmartPtr(Loki)-auto_ptr/movec'torissue]
Peter Dimov wrote: > Howard Hinnant wrote: >> Custom deleter policy + implicit conversion policy - converting >> constructors - converting assignment operators == smart pointer that >> handles arrays. > > - operator* > - operator-> Not these two--at least not for any reasons that I see. > - static_cast > - dynamic_cast > - incomplete type support > - auto_ptr construction/assignment It isn't necessary to explicitly disable all these things that are centered around polymorphic behavior. It would just be wrong to use them, just like it is wrong to use an array polymorphically (for any element but the first). The use of arrays in a way managed by a smart pointer is perfectly acceptable. The issues involved with polymorphism and arrays are problems with certain array usages. The same applies to smart pointers to arrays. It is not _necessary_ to prevent that kind of use. However, you *can* prevent many things simply by having a each interface member function validate against each policy, but it isn't absolutely necessary because the behavior would already mimic the built-in behavior. Each policy could define a flag type to prohibit a certain operation from being used. Whether or not that flag type exists is detectable. Therefore, static assertions can be used to prevent certain operations from compiling in a way that is non-intrusive to all other unrelated policies. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Array support [wasSmartPtr(Loki)-auto_ptr/movec'torissue]
Howard Hinnant wrote: > Custom deleter policy + implicit conversion policy - converting > constructors - converting assignment operators == smart pointer that > handles arrays. A custom deleter policy could prevent the use of converting ctors and assignment. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Array support [was SmartPtr(Loki)-auto_ptr/movec'torissue]
Greg Colvin wrote: > At 07:25 PM 2/4/2003, Paul Mensonides wrote: >> ... >> >> If an implicit conversion to the pointed-to type is provided, there >> is no need to overload the subscript operator: >> >> ... >> >> The same applies to the standing problem of operator->*(). >> >> 2c. > > Yep. More reasons why I prefer that smart pointers have an > operator T*. But my view has always been a minority opinion, > in this as in so many other things. An implicit conversion could easily be an optional feature in a policy-based smart pointer. Custom deleter policy + implicit conversion policy == smart pointer that handles arrays. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Array support [was SmartPtr(Loki)-auto_ptr/movec'torissue]
Andrei Alexandrescu wrote: >> I agree that vector (or vector-like substitutes) are preferred over >> smart_ptr in most circumstances. But there are times when >> ownership of the array needs to be transferred or shared. In those >> instances, vector is not a good fit. smart_ptr > is a >> possibility, but this is typically inferior both in performance, and >> in client level syntax (e.g. (*p)[i] instead of p[i]). > > When designing an amenity, it is important to figure out how the > alternatives work for its target audience. For the limited audience > that (1) needs a smart pointer to an array and (2) is unhappy with > vector's performance, I'd say it's ok to just advice using a SmartPtr > configured > with an array deleter and have them write get_impl(sp)[45] instead of > sp[45]. The super-performance-critical code portions of an app are > not that large and much uglier for different reasons anyway :o). If an implicit conversion to the pointed-to type is provided, there is no need to overload the subscript operator: #include struct sample { inline operator const char*() const { return "01234"; } }; int main() { sample var; std::cout << var[0] << var[1] << &std::endl; return 0; } The same applies to the standing problem of operator->*(). 2c. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: is_class
Daniel Frey wrote: [...] >> I might be misunderstanding you, but the above does not match the >> type "int (X::*)(long, double) const." E.g. if I have this template: > > I think you misunderstood me. I should have made it clearer what I was > refering to when I wrote "matches the above specialization". By this I > was refering to Peters question to find something that is taken by the > > template< class C, typename T > > struct is_member_function_pointer< T C::* const > > { enum { value = is_function< T >::value }; }; > > specialization I provided. At least that is how I understood him. [...] > Yes. My problem is that I still don't understand what Peter is trying > to > show and that makes me kind of nervous :) [deep breath] I think that he thought that you might have thought that the cv-qualified specializations would match pointers-to-cv-qualified-member-functions rather than just cv-qualified-pointers-to-members. [phew] Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Daniel Frey wrote: >> Yes, I worded that incorrectly. I should have said: are you thinking >> that the above will match >> >> int (X::*pf)(long, double) const; > > I'm not absolutely sure, but I think that this creates a non-const > pointer to a const member function. As far as I understand it, this is > equivalent to: > > typedef int ft( long, double ) const; > ft X::* pf; Yes, the type of 'pf' is: int (X::*)(long, double) const; > To create something that matches to above specialization, you have to > do something like this: > > ft X::* const cpf; I might be misunderstanding you, but the above does not match the type "int (X::*)(long, double) const." E.g. if I have this template: #include template struct test { enum { value = false }; }; template struct test { enum { value = true }; }; struct X { }; typedef int (X::* Y)(long, double) const; int main() { std::cout << test::value // false << '\n' << test::value // true << &std::endl; return 0; } In other words, "R C::* const" is a constant pointer-to-member, not a pointer-to-const-member, and certainly not a pointer-to-const-member-function. It *can* match a const-pointer-to-const-member-function, but then the const-qualification of the member function would be hidden in the 'R' type. > Anyway, what is the point of this? I specialize for a pointer and > pointers can be cv-qualified, thus to be complete I have to provide > specializations for all cv-versions, haven't I? That is what I assumed that you meant when I saw those specializations. At this point, I'm not sure, so I'm just clarifying that these two types are _not_ equivalent: typedef void (X::* _1)() const; typedef void F(); typedef F X::* const _2; Type #1 is a pointer-to-const-qualified-member-function. Type #2 is a const-pointer-to-unqualified-member-function. As I said, I may be misunderstanding you. If so, just consider it a clarification for everyone else. As is, the four specializations that you provided with catch any unqualified (first one) or qualified (other three) pointer-to-member. The nested call to 'is_function' should yield true if the pointed-to type a function type (cv-qualified or otherwise). Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] is_class
- Original Message - From: "Daniel Frey" <[EMAIL PROTECTED]> > This not only leads to safer class detection, it also allows us to > implement is_member_function without providing versions for every number > of parameters. This is already possible. The specialization... R C::* ...matches all pointers-to-members, including pointers-to-member-functions. However, when it *does* match a pointer-to-member-function, the type of 'R' is a function type. Therefore, it is possible to detect a pointer-to-member-function like this: template struct is_pointer_to_member_function { enum { value = false }; }; template struct is_pointer_to_member_function { enum { value = is_same::value }; }; ...since only function types are implicitly adjusted to pointer-to-function when used as a parameter. Regards, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] is_class
- Original Message - From: "Daniel Frey" <[EMAIL PROTECTED]> > template< class C, typename T > struct is_member_function_pointer< T C::* > { enum { value = is_function< T >::value }; }; > template< class C, typename T > struct is_member_function_pointer< T C::* const > { enum { value = is_function< T >::value }; }; > template< class C, typename T > struct is_member_function_pointer< T C::* volatile > { enum { value = is_function< T >::value }; }; > template< class C, typename T > struct is_member_function_pointer< T C::* const volatile > { enum { value = is_function< T >::value }; }; Whoa, sorry Daniel, I missed this part, which is almost exactly the same as my post. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] BOOST_PP_XX_INCCLUDE
- Original Message - From: "Hugo Duncan" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Wednesday, January 29, 2003 12:23 PM Subject: [boost] BOOST_PP_XX_INCCLUDE > On Mon, 27 Jan 2003 12:42:14 -0800, "Paul Mensonides" <[EMAIL PROTECTED]> wrote: > > > #define BOOST_PP_HEADERS \ > > (...), /* i.e. "no path" */ \ > > (iostream)(fstream)(vector)(string) \ > > (map)(cstdlib)(sstream) \ > > /**/ > > > > ??=include BOOST_PP_ANGLED_INCLUDE() > > > > effectively does this: > > > > #include > > #include > > #include > > #include > > #include > > #include > > #include > > Looks good to me. Does anyone else have any comments about what they'd like out of such a mechanism? > I would like to take a file that uses BOOST_PP_HEADERS, say > > > #define BOOST_PP_HEADERS \ > > (...), /* i.e. "no path" */ \ > > (iostream)(fstream)(vector)(string) \ > > (map)(cstdlib)(sstream) \ > > /**/ > > > > ??=include BOOST_PP_ANGLED_INCLUDE() > > and preprocess it to generate the file that says > > > #include > > #include > > #include > > #include > > #include > > #include > > #include Ah, you mean _without_ actually including the files? Well, for obvious reasons, this can't be done without a double preprocessor pass, but it is possible. To make such a file, you'd have to write the #include directive manually, something like: #include #include #include #define HASH # #define HEADERS \ (iostream)(fstream)(vector)(string) \ (map)(cstdlib)(sstream) \ /**/ #define BOOST_PP_LOCAL_LIMITS \ (0, BOOST_PP_SEQ_SIZE(HEADERS) - 1) \ /**/ #define BOOST_PP_LOCAL_MACRO(n) \ HASH include \ /**/ #include BOOST_PP_LOCAL_ITERATE() #undef HASH #undef HEADERS Preprocessing this will output a set of include directives: # include # include # include # include # include # include # include However, you may have problems with the pound-sign (#), so you may have to do something more ridiculous like defining HASH like this: #define HASH % ## : %: is the digraph for '#' and prevents it from being a macro expansion operator--i.e. stringizing. Of course, whatever uses the resulting file must be able to handle digraphs. I'm not sure if this is a good solution or not, it is dangerously close to being undefined behavior--if it isn't already. It seems to me that it would be easier to just write it by hand, or use a small program to write it out for you. I don't know, just some thoughts. > > You can simply make a source file that includes all the files that you want > > to pre-preprocess (if that is what your getting at), run it through your > > compiler's preprocessor, and then include the result file. > > I don't think bjam supports just running the preprocessor, but as you say > the poblem is more tricky; I would like to stop preprocessing at a certain > include depth. This I can't do without compiler support. > > but this is outside the scope of the pp-lib can automate because it > > requires a separate build step to produce the preprocessor equivalent of a > > "pre-compiled header." > > I didn't mean to imply it was within scope. I know MPL does preprocessing > using python, but I don't know how reuseable that code is, so I was > just hunting for tips, suggestions and pointers. > > Thanks for your help. Look forward to seeing BOOST_PP_INCLUDE when you have time. I'll write up a copy and send it to you directly to try out. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: MPL include problem with BOOST_PP_ITERATE
- Original Message - From: "Hugo Duncan" <[EMAIL PROTECTED]> > > At one point in the past, however, I wrote a mechanism explicitly for > > including a set of files. It was intended to "shorthand" the process of > > including a lot of files from the same library. Something like: > > > > #define BOOST_PP_HEADERS \ > > (boost/preprocessor, > > (tuple/elem.hpp)(repetition/repeat.hpp)(list/adt.hpp)) \ > > /**/ > > > > #include BOOST_PP_ANGLED_INCLUDE() > > > > (I had BOOST_PP_QUOTED_INCLUDE as well.) I'd be happy to add such a > > mechanism, but I'd like to hear what people want from the mechanism and any > > thoughts on syntactic issues, etc.. > > BOOST_PP_xx_INCLUDE( directory, list_of_filenames_with_paths ) is > good as long as directory can be empty, for the case where the filenames have > different paths. BOOST_PP_xx_INCLUDE(directory, files) is impossible. What you need is a user-defined macro that contains the files that you want, and then include another file that performs all the inclusion. The mechanism that I had handled the "no path" case by using parentheses. For example, (I don't remember the exact syntax that I had, so forgive me if it changes from post to post. The syntax is, of course, open for discussion.) #define BOOST_PP_HEADERS \ (...), /* i.e. "no path" */ \ (iostream)(fstream)(vector)(string) \ (map)(cstdlib)(sstream) \ /**/ ??=include BOOST_PP_ANGLED_INCLUDE() ...effectively does this: #include #include #include #include #include #include #include > The other problem that I have when using this is that it removes > dependencies for the build process. To solve this, the files can > be preprocess. Is there a standard toolset/method for preprocessing > header files ? I'm not sure what you mean here. The arities, and possibly other things, that the MPL can handle is directly dependent on certain macros. If you pre-preprocess the files, you effectively fix the arities to a certain size. Also, you'd have to preprocess the files separately for each compiler that you want to target. Worse, you implicitly undefine all macros used--including include guard macros. You can simply make a source file that includes all the files that you want to pre-preprocess (if that is what your getting at), run it through your compiler's preprocessor, and then include the result file. ...but this is outside the scope of the pp-lib can automate because it requires a separate build step to produce the preprocessor equivalent of a "pre-compiled header." Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_convertible corner case
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > The problems are not insurmountable though (with an "is_valid_expression"). > > You aren't dealing with entire language at this point, only an > > expression. > > And which parts of the language does that fail to drag in? Not many. Variable declarations specifically--that removes quite a few problems from the parser implementation. But, also, declarations and definitions of all types, exception handling try and catch blocks, statements, etc.. I.e. it leaves out most of the stuff that makes the parser complicated. The difficult part of the semantic analysis would still be lookup and overloading, IMHO. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_convertible corner case
- Original Message - From: "Howard Hinnant" <[EMAIL PROTECTED]> > Fortunately circumstances such as the one illustrated above seem to be > rare (at least in my experience). But it is amusing (amazing?) how > many traits like tests are today passing non-POD classes to an > ellipsis, and invoking undefined behavior! :-) It isn't invoking undefined behavior because it isn't passing non-POD classes to an ellipsis--it isn't passing *anything* to an ellipsis. ;) Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_convertible corner case
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > I tend to agree on a "moral/aesthetic" level, but on a practical level > we have to tread carefully. The question, "can we just have an > operator which produces a compile-time constant value saying whether > its operand is a valid expression?" has come up a few times in the > committee. Each time, the implementors looked at their codebases and > said "oooh, that's really hard to do." I think the short form of the > reason is that C++ compilers generally don't have the ability to > recover from errors reliably. That may explain why your 2nd, 3rd, > 4th... diagnostic messages tend to be useless gibberish ;-) > > So, I'd like to push for something like that but practically speaking > I'm not sure how to get there. The problems are not insurmountable though (with an "is_valid_expression"). You aren't dealing with entire language at this point, only an expression. You'd need an independent expression parser that is coupled to the symbol table. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MPL include problem with BOOST_PP_ITERATE
- Original Message - From: "Aleksey Gurtovoy" <[EMAIL PROTECTED]> > Hugo Duncan wrote: > > Maybe my use of ITERATE is slightly different, in that I am using > > it to include a LIST of files. The LIST provides a single > > integration point. Hoisting all the includes reduces the utility > > of using ITERATE. > > OK, I see the problem now. > > > > > I can hoist the include of (and have done so > > for the moment), but I don't think that I should have to. > > > > The way I look at it, the fact that MPL uses ITERATE in its header > > files is an implementation convenience for MPL, and should not be > > visible to the user. > > You have a point, here. I'll look into the issue tonight. Don't bother. What Hugo is doing is a "sketchy" use of the mechanism precisely because of this type of problem. Even if you define a special flag macro to distinguish a certain MPL iteration from some other iteration, you are still going to have serious problems. Specifically, you'd have to rewrite all of it to reenter the file-iteration mechanism in an abstract and relative way, which means no direct references to specific iteration frames at all. This kind of thing is the purpose of the "relative" macros, but I cannot _evaluate_ the filename to iterate over. Therefore, I cannot abstract the depth. ---> It should be considered an absolute rule that you don't include normal headers inside an iteration. <--- (If I missed saying that in the docs, sorry, I'll fix it. I actually thought that I mentioned it, but I haven't checked.) Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: MPL include problem with BOOST_PP_ITERATE
- Original Message - From: "Hugo Duncan" <[EMAIL PROTECTED]> > Maybe my use of ITERATE is slightly different, in that I am using > it to include a LIST of files. The LIST provides a single > integration point. Hoisting all the includes reduces the utility > of using ITERATE. Ah, okay, I see what your saying. You cannot use the file-iteration mechanism this way without near explicit collaboration with the files that your are "including." The problems involved are not as easy to solve as you're are suggesting (see my other post in response to Aleksey). At one point in the past, however, I wrote a mechanism explicitly for including a set of files. It was intended to "shorthand" the process of including a lot of files from the same library. Something like: #define BOOST_PP_HEADERS \ (boost/preprocessor, (tuple/elem.hpp)(repetition/repeat.hpp)(list/adt.hpp)) \ /**/ #include BOOST_PP_ANGLED_INCLUDE() (I had BOOST_PP_QUOTED_INCLUDE as well.) I'd be happy to add such a mechanism, but I'd like to hear what people want from the mechanism and any thoughts on syntactic issues, etc.. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] MPL include problem with BOOST_PP_ITERATE
- Original Message - From: "Hugo Duncan" <[EMAIL PROTECTED]> > I think I have found a problem with boost/mpl/list.hpp > > I am including files using BOOST_PP_ITERATE. One of the files > that I include happens itself to include boost/mpl/list.hpp. I'm not sure what you mean here. If you are iterating over a file (or section of a file) with the file-iteration mechanism. That iterated text should *never* include regular headers. E.g. if '1.hpp' uses the iteration mechanism to iterate over '2.hpp', and '2.hpp' needs the facilities from some other file (like or anything else at all), '1.hpp' can include them, *not* '2.hpp'. If you want to separate concerns as much as possible, you can reference the iterated file as a normal header so it can include other facilities that are needed: // 1.hpp #ifndef ONE_HPP #define ONE_HPP #include #include "2.hpp" // normal inclusion #define BOOST_PP_ITERATION_PARAMS_1 \ (3, (1, 10, "2.hpp")) \ /**/ ??=include BOOST_PP_ITERATE() // not normal at all! #endif // EOF -- // 2.hpp #if !BOOST_PP_IS_ITERATING // as normal header #ifndef TWO_HPP #define TWO_HPP #include #include // etc. #endif // TWO_HPP #else // not normal at all! // use and <../repeat.hpp> facilities... #endif > boost/mpl/list.hpp begins > > #if !defined(BOOST_PP_IS_ITERATING) > / header body > #ifndef BOOST_MPL_LIST_HPP_INCLUDED > #define BOOST_MPL_LIST_HPP_INCLUDED > > > Because I am using BOOST_PP_ITERATE, BOOST_PP_IS_ITERATING is defined, > and problems occur. > > I assume BOOST_PP_IS_ITERATING is checked for logic associated with > preprocessed file generation. It is defined when the file-iteration mechanism is iterating over a file. Its purpose is to distinguish between a normal inclusion and an "iteration" inclusion so that the same file can iterate over itself. When a file that is iterated includes other files *during an iteration*, BOOST_PP_IS_ITERATING is still defined and the other files probably won't know how to handle it. ( is one example of this.) The solution is simply to not include any files during a particular iteration. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_convertible corner case
- Original Message - From: "Gennaro Prota" <[EMAIL PROTECTED]> > >It's a similar problem to what happens > >if the To type has a private constructor taking the From type, my gut > >feeling is that both these cases have to be listed as "undefined behaviour". > > Ouch, no. You will never find me agreeing on this point. This seems > along the lines of "if I can't get it work, then it's undefined > behavior" which is a habit we should all get out of. As Paul > Mensonides wrote me (Paul, I hope you don't mind the quotation), UB is > reasonable e.g. when diagnosing the situation is impractical (for the > compiler), or when platform differences make it difficult to choose a > single specification without penalizing some of them, not when just we > don't know what to do. (I don't think that he means undefined behavior as far as the compiler is concerned, but I haven't been following this thread closely so I might be wrong.) At some point, especially with things of this nature, you have to say "this is valid input, and who knows what happens if you pass something else." This is especially the case when these type of "traits" templates are hacked up to make them work on various compilers--which makes it difficult to list invalid input. The most important issue is whether you can handle the most common and most useful cases. You can, of course, make a documented list of all things that are valid input and maybe as many things that you can think of that aren't for a strictly conforming compiler. You can also try to handle border case situations like this one if at all possible, but you can't always guarantee in the documentation that the border cases will always work with every compiler. I do, however, agree that we need more support from the language for generic programming and some type of standardized API into the compiler's type system. And I definitely think that "undefined behavior" is unreasonable when the situation is easily diagnosable and not platform specific. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Policy-based smart pointers revisisted
s whole thing is blown way out-of-proportion, and > worse has a self-reinforcing nature. You may not believe it, but I > have personally bent over backwards to try to stop this cycle. I believe you. I am not trying to fight a war here. I am only saying that I don't think that Andrei was completely off-base, and that we as a whole can be a little more welcoming--especially to proven experts in C++ design. In fact, I initially said that I didn't want to take sides in the smart pointer debate. > > If so, the standing argument is that "certain people will simply not > > bother to choose." Otherwise, the argument is whether policy > > parameters complicate the interface. > > Or whether the complication buys enough additional power, or, whether > it leads to large systems with smart pointer interoperability > problems, or... > > Not saying I buy any of those arguments; just that there are a few > things to talk about once we have a design to look at. I don't know if we need a concrete design to look at those questions. Ideally, we should decide what the negatives are and see if it is possible to avoid (or minimize) them to an acceptable extent _with_ design. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Re: Policy-based smart pointers revisisted
- Original Message - From: "Edward Diener" <[EMAIL PROTECTED]> > People disagree with others all the time based on their technical > understanding. No one's opinion is exempt from reasonable discussions or > arguments over what someone else perceives as the correct solution to a > technical problem. In the example I mention, which was the sequence abstraction design of the MPL, there was a massive debate on the pros and cons of that design. Ultimately, I consensus was never reached because everybody got tired of arguing. That said, the design was (and probably still is) untested in real code, whereas the simpler design was. To that end, Andrei asked anyone to convince him with a practical code sample that justified the design. It never happened. We had a severe case of several experts fundamentally disagreeing. The only possible resolution was to display the validity of the design with an example, but instead, Andrei's concerns where disregarded altogether, and he was basically told to "deal with it." > I'd argue with William Shakespeare ( or his ghost ) > on poetical drama if I though I had an intelligent comment to make or, more > to the point, with Bjarne Stroustrup on C++. ;) > I am a great admirer of "Modern C++ Design" as I would guess many other C++ > programmers also are. That doesn't make Andrei exempt from other's opinions, > as I am sure he knows, nor do I believe he really thinks it should be so. Yes, I know, and that is not my point at all. > But it is strange that he really thinks he is unpopular with Boost, meaning > people who use or create Boost libraries. I would guess exactly the opposite > since the spur he gave to creative template programming in his book must > certainly have influenced many Boost developers. I'm only calling it like I see it, and I'm not trying to offend anyone. Rather, I'm saying I understand exactly why Andrei feels the way he does. > > > > The same thing looks like it is happening here with policy-based smart > > pointers. It seems to me that arguments are being manufactured to > preclude > > the concept of a policy-based smart pointer (such as incompatibilities and > > the supposed complexity of interface--neither of which I personally think > is > > significant) precisely because it isn't 'shared_ptr' or that it would > > subsume 'shared_ptr'. That may or may not be the case, but that is how it > > comes off to me, and I can see how it would come off that way to others. > > I don't think people are "manufacturing" arguments. They are just bringing > up issues, seeking to discuss them, and make intelligent comments about > ideas which they care. My major point with what I said is that it is sometimes difficult to distinguish religious defense of an argument from practical defense of an argument--and both exist. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Policy-based smart pointers revisisted
ion. > What we do here is to consider > the arguments. Yes, and also engage in little "political wars." It doesn't matter what anyone intended. That is the way things come off sometimes. > > precisely because it isn't 'shared_ptr' or that it would subsume > > 'shared_ptr'. > > As far as I can tell, that's *precisely* how it's been presented > historically: "here's a design which can replace shared_ptr and > auto_ptr and all the rest". > > I don't have a strong opinion about whether a PBSP design should > subsume shared_ptr or not, BTW. I somehow think that the more I say > so, the less I'm believed. Neither do I. > > That may or may not be the case, but that is how it comes off to me, > > and I can see how it would come off that way to others. > > With all due respect, that sounds like a knee-jerk reaction to the > fact that there's any discussion or disagreement with your > point-of-view. Most of the discussion about this particular issue has > been very detached AFAICT. Your response in whole seems like a knee-jerk reaction to justify behavior. That is the way it goes. You have preconceived ideas, as do I. I'm telling you how I interpret it, not whether I think it is absolute fact. Nor am I overly concerned about the pointer issue. I'm only defending that which I think needs to be defended. > > This is precisely why I think that we need both forms. When experts > > disagree fundamentally on such a concept, both forms should be > > supported--and there is no question that both Dave and Andrei (and > > many others here) are experts. > > But I don't think I have a fundamental disagreement with Andrei on > this. Really! How can I convince you? Okay, okay. I believe you. ;) > Andrei will tell you that I wrote to him about 18 months ago because I > wanted to use Loki's smart pointer, but I couldn't because details of > its implementation was going to cost too much space. I can see the > need for something like that, and wish we had it in Boost. I just > happen to also see some merit in the POV of people who are nervous > about the consequences of that kind of design. I think it's worth > discussing a bit to see what the problems and solutions might be. > Sweeping those concerns under the rug or dismissing them as > "insignificant" isn't going to help move anything forward. I didn't sweep them under the rug. I said that "in my personal opinion" they aren't significant. Just as others have said that its their opinion that we don't want a policy-based smart pointer because of reason X and Y. If you take the complexity of interface, which is minimal, and apply that argument across the board, you can kiss the STL, the MPL, the PP lib, and whole host of Boost and non-Boost libraries out the window, because they support "extra parameters" in some form or another that aren't strictly necessary for the default case. > > It is also obvious that Andrei makes an effort to be civil when he > > disagrees (as do many others), but I think that sometimes he gets > > frustrated when people don't understand (or even see) his point of > > view. Actually, that goes for everyone here, and everyone needs to > > keep that in mind and take disagreement with a grain of salt. > > Exactly. In order to reach consensus, we need to have patience with > other peoples' inattention, lack of insight, stubbornness, and > attachment to preconceived notions. Yes, and stop always pointing the finger at others without examining ourselves first. We are *all* guilty of this, so don't sweep my opinion on this subject under the rug either. However, the point being that consensus on some issues will never be reached. We are faced with a question. Is a policy-based smart pointer a good design? Or is it only a bad design because 'shared_ptr' already exists? If so, the standing argument is that "certain people will simply not bother to choose." Otherwise, the argument is whether policy parameters complicate the interface. Neither is a good argument >> IMHO <<, and we have the tools in C++ to solve the latter problem. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: Policy-based smart pointers revisisted
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > If you really care about this, why don't you work on making a boost > submission or bringing a proposal to the committee for the next > meeting? By all means. A policy-based smart pointer doesn't mandate the inclusion of all of Loki--even though there is much in Loki that is worth looking at. > > My feeling is that the boost community would of course be interested > > in looking over a related submission, but most of its members are > > not interested in actively working on such a port. And let's face > > it, I'm not popular with boost, and that doesn't help generating > > enthusiasm inside boost :o). > > I think your perception that your unpopular with boost does more to > hurt your ability to generate enthusiasm than any actual > unpopularity. You seem to have the attitude that the cards are > stacked against you, and to approach boost with a kind of resentment > and resignation that you won't get a fair hearing. I don't want to propagate a war here, but Andrei's perception (of his perception) is not entirely unfounded either. In the past, Andrei has raised some practical concerns with certain design strategies. At that time, his opinion was derided based entirely on, from my perspective, religious devotion to an unproven concept. Andrei asked for practical examples of the utility of those design strategies, and he was effectively told, "If you don't like it, don't use it." I don't want to get into that old argument again, and that is not my intention. I'm merely pointing out that Andrei got flack for presenting an opinion counter to many Boost developers' and standing by that opinion. The fact is that there are many things that various Boost developers will argue over with religious fervor (i.e. another way of saying "political"), and I simply don't believe that people are entirely objective. Their preferences influence their beliefs, and people typically don't take criticism well. That is to be expected. Such is life. The same thing looks like it is happening here with policy-based smart pointers. It seems to me that arguments are being manufactured to preclude the concept of a policy-based smart pointer (such as incompatibilities and the supposed complexity of interface--neither of which I personally think is significant) precisely because it isn't 'shared_ptr' or that it would subsume 'shared_ptr'. That may or may not be the case, but that is how it comes off to me, and I can see how it would come off that way to others. This is precisely why I think that we need both forms. When experts disagree fundamentally on such a concept, both forms should be supported--and there is no question that both Dave and Andrei (and many others here) are experts. If one or the other rarely gets used, then we can revisit that decision at a later date. > You have made real contributions to the work of many people here; I > know the iterator adaptors library would never have arisen as it did > without ideas you sparked years ago about policy-based design. Why > not apply your great intelligence, humour, and ability to communicate > as productively around here as you do elsewhere? Yes, definitely, and there is plenty of credit to go around. I purposefully read every post that Andrei submits to this list--often times because he is humorous as well as intelligent. It is also obvious that Andrei makes an effort to be civil when he disagrees (as do many others), but I think that sometimes he gets frustrated when people don't understand (or even see) his point of view. Actually, that goes for everyone here, and everyone needs to keep that in mind and take disagreement with a grain of salt. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Policy-based smart pointers revisisted
- Original Message - From: "Alisdair Meredith" <[EMAIL PROTECTED]> > The simplicity is simply too big a lure. Although we could tune and > focus our pointers more effectively using policies and Loki, we then > have the complexity of many pointer types running through our code, and > having to remember the nuances of how each one was defined. Using the > basic 3 mentioned above simply cuts out the clutter. I don't buy this argument about the "complexity of many pointer types." I'm not going to make a judgement on whether a few distinct smart pointers are better than a single super pointer. I think we should have both and let users use whichever the like better. However, all smart pointers provide basically the same interface, so keeping track of that is not that big an issue, as the differences in interface exist because of the various purposes of different smart pointers. Also, because smart pointers are templates, you already have a different smart pointer every time that you instantiate it with a different type. The compatibility issues between smart_ptr_A and smart_ptr_B can be handled without significantly more difficulty than smart_ptr and smart_ptr. 2c, Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fw: compile problems on solaris 2.8
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > >> This seems to be a problem with the PP lib and MPL, anyone any ideas? > > > > The config should never even see the BOOST_PP_CHECK_... macros. It should > > be using the Borland configuration: > > > > #define BOOST_PP_CONFIG_FLAGS() BOOST_PP_CONFIG_BCC() > > Which is the case in current CVS, right? I don't know. The current CVS uses the Borland configuration for __BORLANDC__, __IBMC__, __IBMCPP__, __SUNPRO_CC. I assume that __SUNPRO_CC is the operative symbol here, but I don't know if it's the same compiler or not. If not, than whatever compiler it is needs to be added to the config file. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fw: compile problems on solaris 2.8
- Original Message - From: "John Maddock" <[EMAIL PROTECTED]> > This seems to be a problem with the PP lib and MPL, anyone any ideas? The config should never even see the BOOST_PP_CHECK_... macros. It should be using the Borland configuration: #define BOOST_PP_CONFIG_FLAGS() BOOST_PP_CONFIG_BCC() Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Token sequence to sequenceconversionmacros.
- Original Message - From: "Vesa Karvonen" <[EMAIL PROTECTED]> Hi Vesa, > The implementation of RELATION_TO_SEQ() should not be very difficult, but > there is a quick incomplete implementation in this post, that can give some > ideas. A more generic "token sequence" to sequence conversion macro could > also be very useful. Consider the following token sequences: > > 1 0 2 3 > B o o s t SPACE 1 3 1 > > Neither of the above are sequences, but it would be possible to turn them > into sequences using suitable macros (pseudo-code): > > TOKEN_SEQ_TO_SEQ(FIRST, REST, IS_LAST, 1 0 2 3) > ==> (1)(0)(2)(3) > > TOKEN_SEQ_TO_SEQ(FIRST, REST, IS_LAST, B o o s t SPACE 1 3 1) > ==> (B)(o)(o)(s)(t)(SPACE)(1)(3)(1) I already have something almost exactly like this in the high-precision arithmetic that haven't committed yet. Of course, you'd have to have a macro for every letter of the alphabet, every number, and every "miscellaneous" thing like "SPACE". Also, it cannot be made to work on any operators, so you'd need special names for them too. > BTW, the naming of SEQ_HEAD and SEQ_TAIL is, IMO, unfortunate, as they do > not match the precedent made by LIST_FIRST and LIST_REST. IIRC, I polled the > group when I designed the initial list support for naming suggestions and > FIRST/REST was the preferred choice. Even if HEAD and TAIL would, in some > sense, be slightly better, I think that it is more important to try to be > consistent. This is not a big issue, but it could, for instance, be useful > for designing generic sequence manipulation macros. Actually, perhaps there > is a good reason to use the name SEQ_TAIL as a sequence can not be empty. [...] > #define SEQ2 (a,b)(c,d)(e,f) > MAKE_SEQ(2,SEQ2) How about this instead: #define MAKE_SEQ(size, rel) MAKE_SEQ_D(size, rel) #define MAKE_SEQ_D(size, rel) \ BOOST_PP_CAT( \ MAKE_SEQ_A_ ## size rel, \ 0X0 \ )() \ /**/ // size 1 #define MAKE_SEQ_A_1(x) (x) MAKE_SEQ_B_1 #define MAKE_SEQ_B_1(x) (x) MAKE_SEQ_A_1 #define MAKE_SEQ_A_10X0() #define MAKE_SEQ_B_10X0() // size 2 #define MAKE_SEQ_A_2(x, y) ((x, y)) MAKE_SEQ_B_2 #define MAKE_SEQ_B_2(x, y) ((x, y)) MAKE_SEQ_A_2 #define MAKE_SEQ_A_20X0() #define MAKE_SEQ_B_20x0() // size 3 #define MAKE_SEQ_A_3(x, y, z) ((x, y, z)) MAKE_SEQ_B_3 #define MAKE_SEQ_B_3(x, y, z) ((x, y, z)) MAKE_SEQ_A_3 #define MAKE_SEQ_A_30X0() #define MAKE_SEQ_B_30X0() // etc. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost preprocessor library
- Original Message - From: "Pavel Vozenilek" <[EMAIL PROTECTED]> > > I see many pre-processor macros in the reference section of the > > documentation but I don't see any good overview explaining the various > > macros or groups of macros and the ideas behind them. > [snip] > > The "Topics" section gives the overview, just follow the individual pages in > their order. The docs is IMHO very well written. Thanks for your opinion, Pavel. I have far more difficulty writing legible, well-structured documentation that I have writing the code. There is still much room for improvement though Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Boost preprocessor library
quot; Metrowerks is supposedly doing on their preprocessor?) The documentation does have some significant articles on the library facilities that require the user to use more advanced techniques, but the discussion is limited to the use of the library rather than the techniques themselves. As I mentioned previously, feel free to contact me personally, via the Boost list, or via the Boost-Users list if you need help, and I will be happy to help as I am able. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost preprocessor library
- Original Message - From: "Edward Diener" <[EMAIL PROTECTED]> > I don't see any organizational principle in the documentation for explaining > the various macros in the Boost preprocessing library. Would someone please > point me in the right direction ? I'm not sure what you mean. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > Cool, I learn something every day. I assume, though, that if I attempted to > > actually use the second parameter it would become non-deducable, right? > > No, as long as identity::type* matches the type of the parameter > you pass, everything still works. Okay, thanks. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > I didn't know that this was legal: > > > > template struct identity { > > typedef T type; > > }; > > > > template void func(const T&, typename identity::type* = 0); > > > > int main() { > > func(10); > > return 0; > > } > > Sure, T is deducible due to the first argument. Cool, I learn something every day. I assume, though, that if I attempted to actually use the second parameter it would become non-deducable, right? Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > >> template > >> struct X > >> { > >> template > >> X(X const&, typename enable_if::value, > > int*>::type = 0); > > ^ > > It chokes here? > > Sorry, no. I mean the 2nd '<' in that line. Okay. > > Is it legal to use the template parameter 'U' in a non-deduced > > context like that? I'm curious because I thought that it wasn't > > (though I could be wrong). > > Why do you say that's non-deduced? Up to the point of enable_if, it's > standard stuff; that's how shared_ptr conversion works. I didn't know that this was legal: template struct identity { typedef T type; }; template void func(const T&, typename identity::type* = 0); int main() { func(10); return 0; } Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > The latter. It was just an experiment. Fortunately, nothing I'm > doing depends very much on it. It was prompted by the fact that > Borland 5.51 can handle enable_if, but not in a templated constructor: > > template > struct X > { > template > X(X const&, typename enable_if::value, int*>::type = 0); ^ It chokes here? Is it legal to use the template parameter 'U' in a non-deduced context like that? I'm curious because I thought that it wasn't (though I could be wrong). > } > > The parser chokes on the first '<' inside the parens. > > I was going to try attacking it from the other direction, by defining > a conversion operator. Interesting. It was a herculean effort though! Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > I'd prefer it if matching void in a parameter list *were* different > from generating one. The above prevents the use of SFINAE to generate > restricted templated conversion operators. Dave, what exactly are you trying to restrict? The implicit conversion from "some type" to the type you are defining or conversion of the type you are defining to only a selected few types? Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Function Type Typedefs in Classes, Etc.
- Original Message - From: "Paul Mensonides" <[EMAIL PROTECTED]> > > I can't tell what EDG thinks it is, but whatever it is, it's not a > > function type. > > EDG treats it like a special type of function type. For instance, trying to > apply const to it yields a "applying const to a function-type" error. Also, > 'typeid(R).name()' yields "void (int)" which is, of course, a function type. > However, 'is_same::value' yields false. On the other hand, > 'typeid(R).name()', when 'R' is from a const-qualified > pointer-to-member-function, yields "void (int) const", which is obviously > *not* a function type. The best I can make out is that EDG treats it as a > "member function type". Actually, you can make Comeau C++ crash like this (not even an ICE, just a total crash): #include #include template struct get; template struct get { typedef R type; }; struct X { }; get< int (X::*)(void) >::type function; int main(void) { std::cout << typeid(function).name() << &std::endl; return 0; } Everything compiles fine until you attempt the call to typeid. Also, it doesn't allow you to define the function either: get< int (X::*)(void) >::type function; int function(void) { // error return 0; } I'll talk to Daveed about what is going on here. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Function Type Typedefs in Classes, Etc.
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > template struct test; > > > > template struct test { > > typedef R type; > > }; > > > > struct X { }; > > > > test< void (X::*)(int) >::type // what type is this? > > > > Is it a function type, or is it a "member function type"? > > If it's legal, it's a function type. Interestingly, MWCW seems to > think it's: > > void (void *const , const void *const , int) Weird. > But none of the other compilers seem to think it's a function type. I > know that when Howard mentioned that he thought it was natural to get > a function type by stripping the "pointer to member" part from a > pointer to member function in some committee discussion, it generated > a little bit of surprisee at least. Yeah, what about "void (X::*)(int) const"? It seems like it is of type "member function type" since, for obvious reasons, a freestanding function cannot be cv-qualified. > I can't tell what EDG thinks it is, but whatever it is, it's not a > function type. EDG treats it like a special type of function type. For instance, trying to apply const to it yields a "applying const to a function-type" error. Also, 'typeid(R).name()' yields "void (int)" which is, of course, a function type. However, 'is_same::value' yields false. On the other hand, 'typeid(R).name()', when 'R' is from a const-qualified pointer-to-member-function, yields "void (int) const", which is obviously *not* a function type. The best I can make out is that EDG treats it as a "member function type". > GCC thinks it's illegal. Which part? Just the existence of 'R' at all? If that is the case, than GCC is wrong. It looks like we have a hole in the type system here. The specialization: R C::* should catch all pointers-to-members, including pointers-to-member-functions. Therefore, the type 'R' exists, but has no name, and is nothing that you could specify by yourself. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > In other words, the "void" parameter list is fundamentally different than > > "type void". > > That's not a very good test case, though. *Matching* a void parameter > could easily be different from generating one. What about: > > template struct id { typedef T type; }; > struct X > { >void f(id::type); > }; > > "ComeauTest.c", line 4: warning: declaring a void parameter list with a typedef is > nonstandard > operator int(id::type); > > ?? > > I'd prefer it if matching void in a parameter list *were* different > from generating one. The above prevents the use of SFINAE to generate > restricted templated conversion operators. I agree, it would be nice if it was legal, but I don't think it is. The "void" parameter list is not of type "void." Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Function Type Typedefs in Classes, Etc.
- Original Message - From: "Paul Mensonides" <[EMAIL PROTECTED]> > Actually, this works too: So does this: template struct is_ptr_to_mem_fun { enum { value = false }; }; template struct is_ptr_to_mem_fun { private: template static char check(const U O::*); template static char (& check(...))[2]; public: enum { value = sizeof(check(0)) != 1 }; }; Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Function Type Typedefs in Classes, Etc.
- Original Message - From: "Paul Mensonides" <[EMAIL PROTECTED]> Actually, this works too: template struct is_ptr_to_mem_fun { enum { value = false }; }; template struct is_ptr_to_mem_fun { private: template struct helper { enum { value = false }; }; template struct helper { enum { value = true }; }; public: enum { value = helper::value }; }; The idea being that the function type (if that is what it is) is adjusted to a pointer-to-function type. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Fun, only handled by vc6/7!
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > >> Here's an interesting turn-of-the-tables: I was experimenting with > >> using SFINAE to disable conversion operators, and I discovered that > >> almost every compiler except vc6/7 rejects this code: > >> > >> template struct voidify { typedef void type; }; > >> template struct Y {}; > >> struct X > >> { > >> template > >> operator Y (typename voidify::type) const { return Y(); } > >> }; > > > > Is this even legal? I.e. for a user-defined conversion operator to have any > > arguments at all? > > Look twice; the argument is void. I know, but I don't think you can derive a 'void' parameter list that way. E.g. template struct test; // not defined template struct test { }; // defined void f(void) { } int main() { test< &f >(); // error return 0; } In other words, the "void" parameter list is fundamentally different than "type void". Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Function Type Typedefs in Classes, Etc.
Is this well-formed: struct X { typedef void func_t(int); func_t member; }; void X::member(int) { return; } What about: struct X { typedef void func_t(int) const; // ^ func_t member; }; void X::member(int) const { return; } This is the root of my question: template struct test; template struct test { typedef R type; }; struct X { }; test< void (X::*)(int) >::type // what type is this? Is it a function type, or is it a "member function type"? The reason I ask is I'm trying to make a 'is_ptr_to_mem_fun' traits class without massive specialization. This works on Comeau C++: template struct is_ptr_to_mem_fun { enum { value = false }; }; template struct is_ptr_to_mem_fun { private: template static char check(U (*)[1]); template static char (& check(...))[2]; public: enum { value = sizeof(check(0)) != 1 }; }; struct X { }; int main() { std::cout << is_ptr_to_mem_fun< int X::* >::value << ' ' << is_ptr_to_mem_fun< int (X::*)(void) >::value << &std::endl; return 0; } ??? Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Metaprogramming: Using static const or enum?
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > I guess it would depend heavily on the compiler used. For instance, a > > compiler might not actually create the storage at all unless the address of > > the static const is actually needed--which would cause the effect to be > > minimal. On the other hand, unless you mapped all the enumerators of a > > particular value to the same type, you'd have issues with name lookup. > > My proposal with integral_c would do exactly that. Yes, and I like it. ;) The only thing I don't like about it is the potential interplay with the rest of the type system. The mapping to a single type per value is good, but it doesn't completely solve the problem. I just think it is better to steer clear of the situation altogether. I personally only use static const for interface values though and use enumerations for internal values (with casting if necessary). Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Metaprogramming: Using static const or enum?
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > "Paul Mensonides" <[EMAIL PROTECTED]> writes: > > >> > Well, yes. If you do that, however, it removes one of the primary > > reasons > >> > to use enumerations, which is for the syntactic convenience. The only > >> > reason left to use enums is to avoid the static storage of the > >> > values. > >> > >> And to improve compilation and linking speed. > > I haven't done the tests of course, but I'd expect it to be faster > anyway. Allocating space in the link map for the static constant and > resolving it across translation units has to cost something. I guess it would depend heavily on the compiler used. For instance, a compiler might not actually create the storage at all unless the address of the static const is actually needed--which would cause the effect to be minimal. On the other hand, unless you mapped all the enumerators of a particular value to the same type, you'd have issues with name lookup. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Metaprogramming: Using static const or enum?
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > >> Now Y::value and Y::value have the same type. Of course, > >> you will probably want some additional tools in integral_c, like > >> an explicit conversion to an rvalue of type T. > Misread it, sorry. > > Well, yes. If you do that, however, it removes one of the primary reasons > > to use enumerations, which is for the syntactic convenience. The only > > reason left to use enums is to avoid the static storage of the > > values. > > And to improve compilation and linking speed. Only if you never use the enumeration type itself as a function template parameter. > Not if the conversion were explicit: > > int main() { > > f( is_integer::rvalue() ); // better > > return 0; > > } > > That's what I meant all along. I like your name, 'rvalue'. ;) > > The only solution that I see is: > > > > (bool)is_integer::value && (bool)is_integer::value > > Pshaw. "Doctor, it hurts when I do this" > > so-don't-do-it-ly y'rs, It is not me that would do it. The use of enumerations--under a theoretically comforming compiler in this regard--basically tells every user of Boost what they cannot do when it shouldn't make a difference. It is, IMHO, bad for Boost to say, "you can't do this because the implementation does 'x + y' instead of 'int(x) + int(y)'". In order to safeguard Boost from this type of evil, every implementation that does any arithmetic, bitwise, and logical operations on enumeration values would have to be cast first. Likewise, this would put the cast burden on users of the library--particularly other libraries that use Boost. That is a bad policy. As I said before, though, the point is moot because compilers are so disparate in this area. At this point, we *have* to use both. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> ... > I mean that if a metafunction is a template instead of a type you > can't treat it polymorphically with other things, e.g. you can't put > it in a type sequence. Yes, you can with the appropriate binders. That is what I meant. > > struct metafunction { > > template struct actual_metafunction { > > // ... > > }; > > }; > > > > vs. > > > > template struct metafunction { > > // ... > > }; > > mpl::lambda handles the transformation from the latter to the former. Yeah, I retract that statement. ;) It is easy to map them back and forth. > > I'm not saying the convention is bad, just that it has its own set of > > associated problems. > > > >> Other than that, the final interface you show is one that's acheivable > >> without TTP at all. > > > > Yes, you can do it without TTP, but it isn't as clean. (I only had a rough > > idea in my head when I made the remark.) You pay a price for the > > abstraction that you mention by "metafunction polymorphism." > > Hmm? Code clarity. As abstraction goes up, clarity goes down. > > Altogether, I'm quite pleased with the mechanism, as I find the linear > > typelist implementation "neat," and I've never seen anything like that > > implementation. > > libs/python/test/if_else.cpp might be of interest to you. I'll take a look. > > The template classes "fold_left" and "fold_right" are not > > even metafunctions in any normal sense. I wouldn't know what to call them! > > They're interesting to a point, but inflexible. Any given usage is > restricted to working on sequences of a particular length. Yes, however, the intended purpose is as an inline definition, not as a sequence type, and it doesn't require the code replication necessary to support something like "mpl::vector". I'm not saying that it's "super great" overall. I'm merely saying that it amuses me, and I like it. ;) Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Metaprogramming: Using static const or enum?
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > solution: > > > > There is no non-intrusive solution. It must be cast at the call site to a > > common type (such as 'int' or 'bool') in order to avoid replicated template > > instantiation. > > > > */ > > Of course, you can use the first solution with enums as well: > > template > struct integral_c > { >enum value_type { value = N; }; > }; > > template struct Y >: integral_c {}; > > > Now Y::value and Y::value have the same type. Of course, > you will probably want some additional tools in integral_c, like > an explicit conversion to an rvalue of type T. Well, yes. If you do that, however, it removes one of the primary reasons to use enumerations, which is for the syntactic convenience. The only reason left to use enums is to avoid the static storage of the values. The automatic rvalue conversion would be nice, but you'd still get the template instantiation problem if you did this: template void f(const T&); template class is_integer : integral_c { }; template<> class is_integer : integral_c { }; template void f(const T&); int main() { f( is_integer() ); // 'T' == 'is_integer' return 0; } What you need is both 'value' and 'rvalue': template struct integral_c { enum value_type { value = V }; static inline T rvalue() { return value; } }; int main() { f( is_integer::rvalue() ); // better return 0; } This still doesn't solve one other issue though: template T operator && (T, T); // etc. ...which is evil, I agree, but possible. This can still break any arithmetic or logical operations that involve enumerations: is_integer::value && is_integer::value // not constant The only solution that I see is: (bool)is_integer::value && (bool)is_integer::value Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Metaprogramming: Using static const or enum?
- Original Message - From: "Gennaro Prota" <[EMAIL PROTECTED]> > >Incidently, an unnamed type has no linkage. > > I think the issue is a little more subtle in that a) it's names that > have or don't have linkage, not types b) a typedef allows you to give > a name, for linkage purposes, to what C++ calls an 'unnamed type', > e.g.: > >typedef struct { int n; } s; Yeah. However, this doesn't really apply to what I'm talking about with: enum { a, b, c }; Yes, for linkage purposes 'enum xyz { }' is equivalent to 'typedef enum { } xyz'. > Oops. X here has still external linkage, though of course you don't > know its "linkage name" and thus cannot refer it from another > translation unit. Yeah, my mistake. Sorry! Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Metaprogramming: Using static const or enum?
- Original Message - From: "Terje Slettebø" <[EMAIL PROTECTED]> > Right, but members of anonymous namespaces does have external linkage, so > this is not an example of that. That's an advantage over the deprecated > file-scope static, which does have internal linkage, and is therefore > unusable as template parameters. > > The program you give compiles and runs without errors. Oops, my mistake. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > > AFAICT from browsing it quickly, the significance of TTP in your code > is that you are passing templates instead of types as functions in the > interfaces to your metafunctions, which I think is inadvisable, > because it eventually breaks metafunction polymorphism. Not really. That is the purpose of various types of partial binding constructs. The only real way to break metafunction polymorphism is to use non-type template arguments in the the template template parameters, and not even that will totally break it. Strictly not using template template parameters has its own problems since you can't pass namespaces as arguments, etc.. This can complicate a design real quick as you make more and more "indirection" layers: struct metafunction { template struct actual_metafunction { // ... }; }; vs. template struct metafunction { // ... }; I'm not saying the convention is bad, just that it has its own set of associated problems. > Other than that, the final interface you show is one that's acheivable > without TTP at all. Yes, you can do it without TTP, but it isn't as clean. (I only had a rough idea in my head when I made the remark.) You pay a price for the abstraction that you mention by "metafunction polymorphism." The difference is that I prefer to do that abstraction external to the core implementation and provide a bridge layer for common usages. In any case, it turns out to be slightly longer anyway because I forgot about the need for ::template when one (or all) of the parameters a dependent. However, I was going for a general purpose "iterative OR" when I started it, rather than just a solution to the particular problem. I basically just had a general idea of something like this: contains::arg::arg::arg::value ...but the "::template" makes it longer: contains ::template arg ::template arg ::template arg ::value Altogether, I'm quite pleased with the mechanism, as I find the linear typelist implementation "neat," and I've never seen anything like that implementation. The template classes "fold_left" and "fold_right" are not even metafunctions in any normal sense. I wouldn't know what to call them! Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > "Paul Mensonides" <[EMAIL PROTECTED]> writes: > > > Which could be even shorter yet if we could get away with template > > template parameters. > > We can and do. > > How would you imagine it would be spelled with TTP? You asked for it. ;) Beware, this is the work of a sick mind! Basically, this implementation reduces the sample to an inline fold of the form: operation::step::step::step::[ value | type ] ...where 'operation' is the type of operation and where '[ value | type ]' is either 'value' or 'type'. Ultimately, we get something similar to this (with the help of a macro to handle the ::template that is sometimes necessary): is_present item item item item ::value Also, the same underlying implementation is used to build a completely linearized typelist mechanism: typedef gen_typelist item item item item item item item item item ::type integral_types; Here is the implementation (from scratch): // identity: yields its template argument as a typedef template struct identity { typedef T type; }; // map_integral: everyone's favorite plus a typedef //representing the type of its stored value //(this is just a hack because I was too lazy to detect it, //and you can't do it with partial specialization because //of the dependent second parameter.) template struct map_integral : identity { static const T value = V; }; template const T map_integral::value; // has_member_value: metafunction that returns // true if its template argument has a nested value // named 'value' template struct has_member_value { private: template struct helper; template static char check(helper*); template static char (& check(...))[2]; public: static const bool value = sizeof(check(0)) == 1; }; template const bool has_member_value::value; namespace detail { // fold_nil: placeholder for "no previous state" // it is used by fold_right struct fold_nil; // fold_helper: the opposite of fold_nil // it stores state needed for fold_right to reverse // its the element order and use fold_left template struct fold_helper { }; // fold_reversal: metafunction that participates in // building a reversed "list" of elements. template struct fold_reversal; // specialization for "no previous state" template struct fold_reversal { typedef build type; }; // specialization otherwise template struct fold_reversal > { typedef typename fold_reversal< typename build::template step, parent >::type type; }; // value_if: yields a nested static constant if 'T' has // a 'value' member. If so, 'T' must also have a member 'type' // that denotes the 'type' of the static constant. // This can be deduced, but I didn't feel like bothering to // do it here. (This is the reason that map_integral above has // a 'type' typedef.) template::value> struct value_if { }; template struct value_if : map_integral { }; } // detail // the fold_left and fold_right meta-something-or-others // perform an unraveled fold in a strange way: //'fold_left::step::step::step::type' // //effectively yields: //op(transform(Z), op(transform(Y), op(transform(X), state))) // // vice versa with fold_right. // // These 'metafunctions' contain a nested template 'step' // which represents a fold step. These nested templates // inject there own name via inheritance of their parent // classes. This allows the syntax: fold_left<...>::step::step // etc.. I'm not sure if this is actually legal, but it works on Comeau C++. // If it isn't legal, I'd need some kind of jumper typedef that identifies the // base class, which would alter the final syntax to: // fold_left<...>::step::base::step etc. // ...which is trivial handled by local sugar macros anyway. // // the 'op' parameter is the fold operation, which is instantiated // with the current element and the current state. // // the 'state' parameter is the initial state of the accumulation // // the 'transform' parameter is a simple way to modify each element // however you like. The 'is_present' implementation uses this parameter // with a partially bound 'is_same' metafunction, and uses a logical-or // metafunction as the 'op' parameter. The 'identity' metafunction is // the default and simply does nothing. // fold_left template< template class op, class state, template class transform = identity > struct fold_left { template< class element, class apply = typename o
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: "David B. Held" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Thursday, January 09, 2003 1:16 PM Subject: [boost] Re: Re: How to do this in withboost--assert(typeid(T)==typeid(bool) ) > "Paul Mensonides" <[EMAIL PROTECTED]> wrote in message > 000901c2b823$1e7f4aa0$8c00a8c0@c161550b">news:000901c2b823$1e7f4aa0$8c00a8c0@c161550b... > - Original Message - > From: "Terje Slettebø" <[EMAIL PROTECTED]> > > > [...] > > BOOST_STATIC_ASSERT((\ > > boost::is_same::value ||\ > > boost::is_same::value ||\ > > boost::is_same::value ||\ > > boost::is_same::value )); > > And this is still bulkier and less elegant than the two-line MPL solution. > ;) Which could be even shorter yet if we could get away with template template parameters. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: How to do this in withboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: "Terje Slettebø" <[EMAIL PROTECTED]> > > You can just do this as well: > > > > BOOST_STATIC_ASSERT( > > ( boost::is_same::value ) || > > ( boost::is_same::value ) || > > ( boost::is_same::value ) || > > ( boost::is_same::value ); > > ) > > > > In other words, just parenthesize the expressions. > > Or even just the macro parameter: > > BOOST_STATIC_ASSERT((\ > boost::is_same::value ||\ > boost::is_same::value ||\ > boost::is_same::value ||\ > boost::is_same::value )); Yeah, duh. ;) You don't need the backslashes though. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: How to do this in with boost --assert(typeid(T)==typeid(bool) )
- Original Message - From: "Daniel Frey" <[EMAIL PROTECTED]> > On Thu, 09 Jan 2003 20:18:08 +0100, Derek Ross wrote: > > > Daniel Frey wrote: > >> Uhm... don't know about MPL, but isn't this a good example for > >> type_traits? Something like: > >> > >> template > >> bool SetOption(COptionInfo& o, const char* key, const T& value) { > >> BOOST_STATIC_ASSERT( boost::is_same< T, bool >::value || > >> boost::is_same< T, int >::value || > >> boost::is_same< T, double >::value || > >> boost::is_same< T, std::string >::value ); > >> ...etc... > > > > It doesn't compile because the commas in the is_same template confuse > > the macro preprocessor. > > > > The error message is: > > > > "macro "BOOST_STATIC_ASSERT" passed 5 arguments, but takes just 1" > > > > Thought you might be interested... > > Yes, sorry. I haven't tested this stuff, this is why I said "Something > like" ;) > > Then how about: > > template > bool SetOption(COptionInfo& o, const char* key, const T& value) { > typedef boost::is_same< T, bool > is_bool_; > typedef boost::is_same< T, int > is_int_; > typedef boost::is_same< T, double > is_double_; > typedef boost::is_same< T, std::string > is_string_; > BOOST_STATIC_ASSERT( is_bool_::value || > is_int_::value || > is_double_::value || > is_string_::value ); >...etc... > > (That's the "usual" work-around for the comma-in-macro problem :) > > Regards, Daniel You can just do this as well: BOOST_STATIC_ASSERT( ( boost::is_same::value ) || ( boost::is_same::value ) || ( boost::is_same::value ) || ( boost::is_same::value ); ) In other words, just parenthesize the expressions. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Metaprogramming: Using static const or enum?
- Original Message - From: "Terje Slettebø" <[EMAIL PROTECTED]> > > And since there are techniques for making out-of-class definitions easier > > (and automatic), which may be instantiated if needed, like you showed, then > > static const seems clearly best. > > That's not nearly so easy to take care of if the metafunction in > question is something like alignment_of which could potentially > have lots of values, depending on the T chosen. In what way would this affect Paul's suggestion: template struct map_integral { static const T value = V; }; template const T map_integral::value; By the way, this could have been done with mpl::integral_c, as well, provided the out-of-class definition is given. Do you maybe refer to that each value may take up space in the executable, if used in such a way that instantiation is needed? That's right, and that's not the case for enum. Still, there are the issues for enum, as well. You would have to have more than one "map_integral" with a different value name, where the values are dependent on one another and are part of the public interface. It isn't a complete solution, but it does work in most cases. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Small thing: yes_type and no_type made public?
- Original Message - From: "Terje Slettebø" <[EMAIL PROTECTED]> > Looks good. What should we call it? size_descriptor, like here? I'm not suggesting you do it exactly that way. Rather, I'm just suggesting that you don't use the pp-lib for something so trivially solved by the template mechanism. As Dave mentioned, the Python lib already has such a thing--though, if I recall correctly, it is being used as a workaround for certain compilers. I personally don't even bother with the typedefs: template struct is_class { private: template static char check(int U::*); template static char (& check(...))[2]; public: static const bool value = sizeof(check(0)) == 1; }; template const bool is_class::value; Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Metaprogramming: Using static const or enum?
- Original Message - From: "Daniel Frey" <[EMAIL PROTECTED]> Terje Slettebø wrote: > > > Just to make sure: Do you "vote" in favor of enums? I have seen problems > > with 'static const ...', but I have never seen problems with enums > > (although they theoretically exist). > > Not just theoretically. As mentioned in an earlier posting in this thread, > BCC doesn't work well with enums, but it does work with static const. Also, > there's the issues pointed out by Paul Mensonides, due to the fact that > enums are UDTs. > Sorry, I should have been more exact. Of course we can only choose a > "default" implementation. If a compiler is buggy, we need to work-around > anyway. The drawback of enums, mentioned by Paul, is the one I call > theoretically, as I have never found this to be a problem in the real > world (well, in *my* real world :). A problem like this can be *created* > but special code which I have yet to see in "normal" programs. OTOH I > have already seen a colleage wondering about link-failures due to > passing a 'static const int ...' to a function which took a 'const T&'. > I consider this much more likely to happen in daily programming, YMMV :) The lack of problems in the "real world" is partially because compilers don't implement enumerations correctly. Even Comeau C++ gets this wrong (as in the small code sample I sent earlier in this thread). The problems associated with the use of enum are problems that cannot be directly avoided. They break encapsulation, and it is not the library's business whether a user does or doesn't do something that can affect the library internally but shouldn't. This is precisely the reason that macros are so derided--they cut across encapsulation boundaries. This reference problem, incidently, comes primarily from arguments to functions that are templated--either by themselves or as members of a class template. Otherwise, it should be a non-issue because there is no good reason to pass an integral constant by reference to const. This problem is typically bypassed by using enumeration values instead. However, this raises another interesting problem. Many enumerations used for this purpose are unnamed: template struct is_ptr { enum { value = false }; }; template struct is_ptr { enum { value = true }; }; This has its own problem in the same templated "pass by reference" situation. Namely, a template type argument cannot refer to an unnamed type: template T func(const T& ref) { return ref; } int main() { func( is_ptr::value ); // error: argument deduction yields unnamed type return 0; } The only way to solve this problem is to make a name for every enumeration type, rather than just the enumerators. However, this has its own associated problems--not even counting the annoyance of having to name the enumeration. It can cause code bloat by instantiated templates: template class A { // ... enum val_t { value = /* ??? */ }; }; template class B { // ... enum val_t { value = /* ??? */ }; }; template void f(const T& ref) { // ... return; } int main() { // two unique instantiations of 'f'... f(A::value); f(B::value); return 0; } Unfortunately, as it is now, because compilers don't support enumerations and static constants properly, we have a limitation that says "this value cannot be used as anything but a constant value, not even as a function argument of any kind without a user-specified cast at the call site." The reason is simple, unless we use only 'static const int' or enum (depending on the compiler) overload results can change from platform to platform. This makes the current mechanism very delicate--the only thorough solution is to cast the enumerator to int, bool, or whatever before any arithmetic, since there is no way that user code can break it. There are strengths to both enumerations and static constants. Given a perfect world (of compilers that is), enumerations only have two advantages: 1) they are syntactically easier to specify, and 2) they are pure values, i.e. built-in temporaries, as far as const& is concerned. Enumerations have downsides as well: 1) they are user-defined types, and therefore, user code can change integral constant expressions inside the library to runtime expressions, which has the potential to break the entire library, 2) they are not strongly typed in a way that helps distinguish the purpose of the value, and 3) they are uniquely typed, which has the potential to cause code bloat. Static constants, on the other hand, have couple of advantages also: 1) they are strongly typed, which conveys meaning and overloading that matches that meaning, and 2) they are encapsulated so as not to inter
Re: [boost] Re: Small thing: yes_type and no_type made public?
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > >> Careful; isn't the symbol "_t" reserved to the implementation in this > > context? > > > > I thought it was only if the underscore was followed by a capital letter, as > > in "_T". > > 17.4.3.1.2 Global names > 1 Certain sets of names and function signatures are always reserved to > the implementation: > > --- Each name that contains a double underscore (_ _) or begins with > an underscore followed by an upper- case letter (2.11) is reserved to > the implementation for any use. > > --- Each name that begins with an underscore is reserved to the > implementation for use as a name in the global namespace. 165) > > I guess the global namespace doesn't apply to macros, huh ;-) This is a good question. The obvious reasoning is to protect library names and extention keywords from macros in particular. However, what is this: namespace A { struct _xyz { }; #define MACRO(id) id MACRO(_xyz) var; } // A In other words, once '_xyz' goes into the macro as an argument, it *could* be considered to be in the global scope. However, I think that is partially the purpose of the second half of bullet one above (i.e. '_U')--to distinguish between macro identifiers and regular C++ identifiers. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Small thing: yes_type and no_type made public?
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> To: "Boost mailing list" <[EMAIL PROTECTED]> Sent: Wednesday, January 08, 2003 12:14 PM Subject: Re: [boost] Re: Small thing: yes_type and no_type made public? > [EMAIL PROTECTED] (Hartmut Kaiser) writes: > > > > > // The following expands to > > // > > // typedef char (&sizeN_t)[N]; > > // > > // for N = 1..BOOST_MAX_SIZETYPE_COUNT > > #define SIZETYPE(z, n, nil) \ > > typedef char (&size ## n ## _t)[n]; \ > > /**/ > > Careful; isn't the symbol "_t" reserved to the implementation in this context? I thought it was only if the underscore was followed by a capital letter, as in "_T". Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Small thing: yes_type and no_type made public?
- Original Message - From: "Hartmut Kaiser" <[EMAIL PROTECTED]> > David B. Held wrote: > > > "Terje Slettebø" <[EMAIL PROTECTED]> wrote in message > > 05ab01c2b695$2f125c70$cb6c6f50@pc">news:05ab01c2b695$2f125c70$cb6c6f50@pc... > > > Sure, that would be fine. I'm not that familiar with > > Boost.PP, though, > > > so I think I leave it to someone else to write that > > version. As quite a > > > bit of code uses yes_type/no_type, now, it may be a good > > idea to keep > > > them, as well, anyway, for backwards compatibility and simplicity. > > > > Using the PP lib seems like overkill to me. > > I think, that using the PP library will give us the possibility to > configure the maximum number of required sizetype typedefs. I've > attached a version of the yes_no_type.hpp, which does so by defining a > constant 'BOOST_MAX_SIZETYPE_COUNT' if this constant isn't already > predefined by the user. > > Regards Hartmut Just a small point, you should include after your normal include guard. While it won't change the result, it is a waste of time to include it prior to the include guard. One other slight problem is that BOOST_PP_REPEAT goes from 0 to N, which will cause you to get this declaration: typedef char (&size0_t)[0]; ...which is illegal. Separately, I don't particularly think that this is a good use of the pp-lib. You can achieve the effect you want easily: template struct size_descriptor { typedef char (& type)[I]; }; typedef size_descriptor<1>::type yes_type; typedef size_descriptor<2>::type no_type; ...or something similar, which solves the problem once and for all. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Metaprogramming: Using static const or enum?
- Original Message - From: "Paul Mensonides" <[EMAIL PROTECTED]> > Actually, this seems to be a bug in Comeau C++: > > #include > #include > > struct A { > enum type { x, y }; > }; > > template struct B { }; > > template inline T operator+(T lhs, T rhs) { > throw 0; > } > > int main() try { > std::cout > << typeid( B ).name() << &std::endl >// ^ >// Comeau C++ doesn't flag this, >// but I think it should. >// Am I wrong here? > << A::x + A::y << &std::endl; > } > catch (int) { > std::cout << "template operator used" << &std::endl; > return 0; > } FYI, I submitted this bug to the EDG guys. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Metaprogramming: Using static const or enum?
- Original Message - From: "Paul Mensonides" <[EMAIL PROTECTED]> > Just my 2 cents. Make that 3 cents... In summary, enumerations are distinct types and therefore can interfere with the rest of the language. Particularly, constant expressions, overloading, operator overloading, template type deduction, etc.. Personally, I think that is a strong case *against* using enumerations. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Metaprogramming: Using static const or enum?
- Original Message - From: "Gennaro Prota" <[EMAIL PROTECTED]> [...] >I like static const, as I think it conveys more succinctly what it's about, >and the enum appears more like a hack (for compilers not handling static >const in-class initialisation). However, if this means it may need an >out-of-class definition, as well, perhaps this could need to be >reconsidered? I like the strong-typing implied by the use of static const, and therefore the overload simplication if it is ever used in such a fashion. The out-of-class definition is annoying, so I tend to do this: template struct map_integral { static const T value = V; }; template const T map_integral::value; ...and then reuse it: template struct is_ptr : map_integral { }; template struct is_ptr : map_integral { }; This removes the need to make the out-of-class definition unless more than one value is present (which can be handled similarly). It also maps each value to the same storage. So, for example, there are only two addresses necessary for boolean values. Furthermore, enumerations can have overloaded operators. Consider the case of "x + y" where both are enumerators. By default, everything is fine because you have int(x) + int(y). If a template operator+ just happens to be defined though, suddenly a bunch of "constant expressions" are no longer constant. Actually, this seems to be a bug in Comeau C++: #include #include struct A { enum type { x, y }; }; template struct B { }; template inline T operator+(T lhs, T rhs) { throw 0; } int main() try { std::cout << typeid( B ).name() << &std::endl // ^ // Comeau C++ doesn't flag this, // but I think it should. // Am I wrong here? << A::x + A::y << &std::endl; } catch (int) { std::cout << "template operator used" << &std::endl; return 0; } Better yet, if you remove the name "type" from the enumeration (ala 'enum { x, y }') you'll get a compile-time error for attempting to use an unnamed type as a template argument. Just my 2 cents. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Alternatives to defined(x)
- Original Message - From: "Paul Mensonides" <[EMAIL PROTECTED]> > Anyway, I might still be able to make the original ideal work with VC and > Metrowerks. (You wouldn't believe how sick I am of those two compilers!) > Give me some time Actually it is not possible anyway. Not necessarily because of VC and Metrowerks though, but rather because of Borland, Sun, IBM, etc.. The root problem is this: x TEST_MACRO If 'x' is the name of a function-like macro, those preprocessors will effectively concatenate 'x' to 'TEST_MACRO'. This makes it impossible to use extended semantics that allow you to pass a function-like macro. In any case, I implemented everything and put it in the CVS: #include #include #include Vesa, I just used my own copyright stuff, since I didn't know what to use otherwise. If you want me to change it, let me know what you want me to change it to. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Alternatives to defined(x)
- Original Message - From: "Vesa Karvonen" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Sunday, January 05, 2003 3:45 PM Subject: Re: [boost] Boost.Preprocessor: Alternatives to defined(x) > David Abrahams: > > > Paul Mensonides: > > > > The semantic change is that 'x' must not be a function-like macro. >^^^ > [...] > >How can you use a macro which only tells you if a function-like macro > >is defined to tell you if an object-like macro is defined? > > >If we could do that, couldn't you implement your original intended > >semantics? > > Well, yes. It could be used for testing whether an object-like config macro > has been defined. > > Actually, since it is not currently possible (portable) to pass around empty > parameters, it really shouldn't make much difference that function-like > macros may not be tested. That is why I said the semantic change was minor. The major difference is that it disallows passing any function-like macro that takes any arguments into the IS_EMPTY macro. It can still be used to test object-like macros. Anyway, I might still be able to make the original ideal work with VC and Metrowerks. (You wouldn't believe how sick I am of those two compilers!) Give me some time Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Alternatives to defined(x)
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > > Well, it does rule out some use-cases, and it is not ideal to have such limitations, but it should > > still be useful for testing whether an object-like macro, such as an include guard, or a config > > macro, has been defined. I think that there are many uses for the > > macro. > > How can you use a macro which only tells you if a function-like macro > is defined to tell you if an object-like macro is defined? No, it only tells you if an object-like macro is defined or not. If a function-like macro is passed into the "function," it will more than likely result in an attempted call of the macro with insufficient arguments--which is illegal. I.e. this would be fine: #define MY_CONFIG_MACRO IS_EMPTY( MY_CONFIG_MACRO ) // 1 ...while this is not a valid input: #define MY_CONFIG_MACRO(a, b) IS_EMPTY( MY_CONFIG_MACRO ) // error insufficient arguments Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Alternatives to defined(x)
- Original Message - From: "Vesa Karvonen" <[EMAIL PROTECTED]> > By the way, I just found the following article (after I posted my proposed > IS_EMPTY()): > > http://groups.google.com/groups?q=is_empty+paul+mensonides&hl=en&lr=&ie=UTF- 8&oe=UTF-8&selm=2HB49.54872%24D36.57225%40rwcrnsc53&rnum=1 > > Interesting stuff. Yeah. I see no way of fully detecting an empty argument without well-defined behavior when token-pasting results in multiple tokens. This is exactly, IMHO, the type of thing that should be well-defined. It is not dependent on the platform or architecture; it is just left undefined for no reason. :( Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Alternatives to defined(x)
- Original Message - From: "Paul Mensonides" <[EMAIL PROTECTED]> > Vesa, I hack this up so it works on all compilers and then add it to the > CVS. The main problem is that the implementation relies on expansion order. > That is another name for "VC and Metrowerks bugs." I don't see why they > can't be worked around though. Vesa, I can get it to work on VC and Metrowerks if I alter the semantics slightly. Namely by doing this: #define IS_ZERO(x) IS_ZERO_I( CHECK x () ) // ... #define CHECK() 1 The semantic change is that 'x' must not be a function-like macro. What do you think? Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Alternatives to defined(x)
- Original Message - From: "Vesa Karvonen" <[EMAIL PROTECTED]> Vesa, I hack this up so it works on all compilers and then add it to the CVS. The main problem is that the implementation relies on expansion order. That is another name for "VC and Metrowerks bugs." I don't see why they can't be worked around though. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: Alternatives to defined(x)
- Original Message - From: "David Abrahams" <[EMAIL PROTECTED]> > "Vesa Karvonen" <[EMAIL PROTECTED]> writes: > > > I'd like to propose adding suitable predicate macros, in particular > > BOOST_PP_IS_EMPTY(X), BOOST_PP_IS_1(X), BOOST_PP_IS_EMPTY_OR_1(X), > > I like them (and I like the implementations)! I like the implementations too. Unfortunately, it won't work on cl (and likely mwcc). I'll need to hack the implementations up a bit. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Boost.Preprocessor: LPAREN & RPAREN
- Original Message - From: "Vesa Karvonen" <[EMAIL PROTECTED]> > Hi, > > I have never used these two macros, but is the following code, from > "boost/preprocessor/punctuation/paren.hpp", correct? > # define BOOST_PP_RPAREN() ( Yeah, I fixed it. Oops. > By the way, I think that the copyright on this file (and probably a few > others as well) is incorrect (I don't recall creating it for Housemarque). > CVS shows that this file was first committed by Paul. I fixed these as well. Paul Mensonides ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost