[boost] Re: is_class
On Wed, 19 Feb 2003 16:09:26 +0200, "Rani Sharoni" <[EMAIL PROTECTED]> wrote: >> // fire-prevention >> template >> Burn ref(T*); >You can improve it to deal with qualified function types (you can't have >pointers or references for such types): Right. However the version with the (pointer to) array Burn ref(T(*)[1]); requires a compiler which doesn't give an error for abstract classes (as settled by core 337). If one doesn't have it then it's probably better giving up qualified function types than abstract classes, being the latter more common than the former. >>[...] >> BTW, I've seen how complex boost::is_reference is. Why so? What >> compiler(s) cause(s) most problems? > >VC6 is problematic since the usual techniques to simulate partial >specialization ICEd it. > >I remember that I came up with the same VC6 trick before I saw it in boost >and I wonder who invented it. Hmm... Why I'm not surprised it was VC? Just to do a little experimenting a gave it a try, and I'm posting here some "discoveries" so that this waste of time can be useful for someone else too :-) Well, at the first shot, I wrote this: template no check_is_reference (U*); // VC++ fails in some cases with this. // (yeah, it's able to form pointers // to references!!!) template yes check_is_reference (...); template struct is_reference { BOOST_STATIC_CONSTANT(bool, value = sizeof(yes) == sizeof (::check_is_reference( 0 )) ); }; but as you can see from the comments VC++ is able to break it :-) As I've seen, it can easily form "pointers to references". For instance: template void f(T* p) { } f(0); // <-- works! The problem arises when you try to use the pointer, of course. Example: template T f(T* p) { return *p; // (1) } f(0); Here the line marked with (1) gives: cannot convert from 'int *' to 'int &' which shows that in this context our pointer to reference is actually a pointer to pointer (at least if the error message is reliable). And that's already nice to know for those who must cope with VC++. On second try, I slightly modified the is_enum code to: template no check_is_reference (U*); template yes check_is_reference (...); template struct is_reference { static T t; BOOST_STATIC_CONSTANT(bool, value = sizeof(yes) == sizeof (::check_is_reference( &t )) ); }; In this case it seems to work. Of course it is a mystery why now it doesn't form pointers to references anymore. Furthermore, it now even seems to work too much! :-) That is, instead of failing for abstract classes and function types it kindly fails on the former only :-) What a strange world... BTW, under VC++ the boost version (release 1.29.0) of is_reference gives false positives with function types. Genny. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
Gennaro Prota wrote: > On Tue, 18 Feb 2003 19:14:50 +0200, "Rani Sharoni" > <[EMAIL PROTECTED]> wrote: > >> This is very nice technique. Just notice that you also need to >> handle void, functions and arrays types. >> >> Abstract classes, functions and array types will fail the completion >> on the burn conversion operator since they are not allowed as >> returns types. > > Yeah. The code was just to give the idea, which I could have expressed > in English if it wasn't that my English is even worse than my C++ :-) > > >> IMHO the main achievement of your technique is that, unlike >> techniques that use conversion constructor to burn user defined >> conversion, its works for incomplete classes (EDG and GCC complain >> when trying to pass lvalue of incomplete class to function that take >> ellipsis as an argument). > > Yes. Attempting lvalue-to-rvalue conversion of an expression of > incomplete type makes the program ill-formed. Sure. 5.2.2/7. It's easy to overlook this case. > Nice :-) BTW, you can avoid the select_type machinery: Thanks > > template > struct Burn { > operator T&() const; > }; > > // fire-prevention > template > Burn ref(T*); You can improve it to deal with qualified function types (you can't have pointers or references for such types): Burn ref(T(*)[1]); > template > char* ref(...); > > // outside the is_enum<> template > // to help gcc > // > yes is_enum_checker (unsigned long); > no is_enum_checker (...); > > > template > struct is_enum { > >static const bool value = > !is_integral::value > && !is_floating::value > && sizeof(yes) == sizeof( is_enum_checker (ref(0)) ); > }; > > > But this simple stuff is already enough to knock out a lot of > compilers :-/ > > BTW, I've seen how complex boost::is_reference is. Why so? What > compiler(s) cause(s) most problems? VC6 is problematic since the usual techniques to simulate partial specialization ICEd it. I remember that I came up with the same VC6 trick before I saw it in boost and I wonder who invented it. Rani ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Tue, 18 Feb 2003 19:14:50 +0200, "Rani Sharoni" <[EMAIL PROTECTED]> wrote: >This is very nice technique. Just notice that you also need to handle void, >functions and arrays types. > >Abstract classes, functions and array types will fail the completion on the >burn conversion operator since they are not allowed as returns types. Yeah. The code was just to give the idea, which I could have expressed in English if it wasn't that my English is even worse than my C++ :-) >IMHO the main achievement of your technique is that, unlike techniques that >use conversion constructor to burn user defined conversion, its works for >incomplete classes (EDG and GCC complain when trying to pass lvalue of >incomplete class to function that take ellipsis as an argument). Yes. Attempting lvalue-to-rvalue conversion of an expression of incomplete type makes the program ill-formed. >Here is a possible is_enum implementation using your technique: > > >template struct convertible { operator T&() const; }; > >template >struct is_enum2 >{ >static yes test(int); >static no test(...); > >struct not_enum {}; > >typedef typename select_type< is_fundamental::value || >is_reference::value, not_enum, convertible >::type T2; > >static T2& make(); >}; > > > >template >struct is_enum >{ >enum { value = sizeof(is_enum2::test(is_enum2::make())) == >sizeof(yes) } ; >}; Nice :-) BTW, you can avoid the select_type machinery: template struct Burn { operator T&() const; }; // fire-prevention template Burn ref(T*); template char* ref(...); // outside the is_enum<> template // to help gcc // yes is_enum_checker (unsigned long); no is_enum_checker (...); template struct is_enum { static const bool value = !is_integral::value && !is_floating::value && sizeof(yes) == sizeof( is_enum_checker (ref(0)) ); }; But this simple stuff is already enough to knock out a lot of compilers :-/ BTW, I've seen how complex boost::is_reference is. Why so? What compiler(s) cause(s) most problems? Genny. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Rani Sharoni wrote: > > You can probably use a similar approach to implement yet another > is_class (not void, reference and doesn't have an implicit standard > conversion to bool). I wonder whether "int () const" has an implicit standard conversion to bool. ;-) ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
Gennaro Prota wrote: > On Mon, 17 Feb 2003 10:02:58 +0100, Daniel Frey > <[EMAIL PROTECTED]> wrote: > >> I started to implement my own type-traits to see if I can do it and >> to >> learn something. While doing so, my design lead me to some >> dependencies: > >> is_enum needed is_class > > Daniel, my apologies in advance if this is just a stupid comment. I'm > again jumping in without actually following the thread (not enough > time), however if I had to implement is_enum the first property that I > would try exploiting is the built-in convertibility (of an rvalue) to > integral types. If you immediately burn the one user-defined > conversion allowed in any implicit conversion sequence there's no need > to exclude classes, I think. The basic idea is: This is very nice technique. Just notice that you also need to handle void, functions and arrays types. Abstract classes, functions and array types will fail the completion on the burn conversion operator since they are not allowed as returns types. IMHO the main achievement of your technique is that, unlike techniques that use conversion constructor to burn user defined conversion, its works for incomplete classes (EDG and GCC complain when trying to pass lvalue of incomplete class to function that take ellipsis as an argument). Here is a possible is_enum implementation using your technique: template struct convertible { operator T&() const; }; template struct is_enum2 { static yes test(int); static no test(...); struct not_enum {}; typedef typename select_type< is_fundamental::value || is_reference::value, not_enum, convertible >::type T2; static T2& make(); }; template struct is_enum { enum { value = sizeof(is_enum2::test(is_enum2::make())) == sizeof(yes) } ; }; I compiled the above code (using the appropriate is_fundamental and is_reference) with Comeau 4.3.0.1, GCC3.2 and EDG. You can probably use a similar approach to implement yet another is_class (not void, reference and doesn't have an implicit standard conversion to bool). Cheers, Rani ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Gennaro Prota wrote: > > On Mon, 17 Feb 2003 10:02:58 +0100, Daniel Frey > <[EMAIL PROTECTED]> wrote: > > >I started to implement my own type-traits to see if I can do it and to > >learn something. While doing so, my design lead me to some dependencies: > > >is_enum needed is_class > > Daniel, my apologies in advance if this is just a stupid comment. I'm > again jumping in without actually following the thread (not enough > > [snipped is_enum-implementation] > > The above is absolutely untested and off the top of my head so take it > with great great prudence :-) It was just to say that, if I'm not > mistaken, is_enum doesn't need is_class. Maybe. Yes, is_enum doesn't need is_class. It was just the case in my implementation at the time I started because I finished is_class first and is_enum was then very easy to implement based on is_class - I just forgot to look for a direct way to do is_enum. Meanwhile I know that there are much better ways, but the above was just to explain how I took the wrong direction. Regards, Daniel -- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: [EMAIL PROTECTED], web: http://www.aixigo.de ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Mon, 17 Feb 2003 10:02:58 +0100, Daniel Frey <[EMAIL PROTECTED]> wrote: >I started to implement my own type-traits to see if I can do it and to >learn something. While doing so, my design lead me to some dependencies: >is_enum needed is_class Daniel, my apologies in advance if this is just a stupid comment. I'm again jumping in without actually following the thread (not enough time), however if I had to implement is_enum the first property that I would try exploiting is the built-in convertibility (of an rvalue) to integral types. If you immediately burn the one user-defined conversion allowed in any implicit conversion sequence there's no need to exclude classes, I think. The basic idea is: template struct is_integral { static const bool value = false; }; #define THIS_IS_INTEGRAL(t)\ template <> struct is_integral { \ static const bool value = true; \ } \ /**/ template struct is_floating { static const bool value = false; }; #define THIS_IS_FLOATING(t)\ template<> struct is_floating { \ static const bool value = true; \ } ... /* add cv-qualified specs here */ ... /**/ THIS_IS_INTEGRAL(bool); THIS_IS_INTEGRAL(char); THIS_IS_INTEGRAL(wchar_t); THIS_IS_INTEGRAL(signed char); THIS_IS_INTEGRAL(short); THIS_IS_INTEGRAL(int); THIS_IS_INTEGRAL(long); THIS_IS_INTEGRAL(unsigned char); THIS_IS_INTEGRAL(unsigned short); THIS_IS_INTEGRAL(unsigned int); THIS_IS_INTEGRAL(unsigned long); THIS_IS_FLOATING(float); THIS_IS_FLOATING(double); THIS_IS_FLOATING(long double); template struct is_enum { struct Burn { operator T() const; }; typedef char yes; typedef char(&no)[2]; static yes is_it(unsigned long); static no is_it(...); template static no check_rvalue(U&); static yes check_rvalue(...); static T get_T(); static const bool value = !is_integral::value && !is_floating::value && sizeof(yes) == sizeof( is_it( Burn() ) ) && sizeof(yes) == sizeof( check_rvalue( get_T() ) ) ; }; The above is absolutely untested and off the top of my head so take it with great great prudence :-) It was just to say that, if I'm not mistaken, is_enum doesn't need is_class. Maybe. Genny. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Mon, 17 Feb 2003 08:34:24 -0500, David Abrahams <[EMAIL PROTECTED]> wrote: >I think even Intel 7 is using the old front-end, but Intel 6 >certainly. I don't know whether you'll _notice_ a difference, though. I don't know what is, in context, the "old front-end" here. However Intel C++ 7 for Windows uses EDG 3.0 (even if they haven't export). Don't know about the Linux version though (I don't know pretty much anything in this post... :-)) Genny. ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
> > No, I would prefer > > > > #if BOOST_WORKAROUND(__HP_aCC, <=33900) || > > BOOST_WORKAROUND(__VisualAge, <=12345) > > template struct enable_if; > > #else > > template struct enable_if; > > #endif > > > > I already explained the reason: C++ compiler vendors use Boost with > > BOOST_NO_CONFIG for conformance testing. I'd rather see broken > > compilers get fixed than developers forever spending time finding > > workarounds. > > OK, agreed. Given that we use another approach for static constants, > what do you think about: > > template< BOOST_UNUSED_TEMPLATE_PARAMETER( bool, cond ), > BOOST_UNUSED_TEMPLATE_PARAMETER( typename, T ) > > struct enable_if; > > Or should we instead replace BOOST_STATIC_CONSTANT by a #ifdef, too? Or > is BOOST_STATIC_CONSTANT different, probably because there is no "right" > code and a workaround, but there are two equally good ways to declare > static constants? Yes, I think a distinction can be drawn between the declaration of integer constants and the present issue. As I was recently reminded in another thread, Boost uses BOOST_NO_... for all defects, so the name you propose is perhaps not the most suitable. The construct itself seems satisfactory, I don't have a firm preference between the two forms. Anyway, let's not get stuck in the bicycle shed. ;-) Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Dave Gomboc wrote: > > No, I would prefer > > #if BOOST_WORKAROUND(__HP_aCC, <=33900) || BOOST_WORKAROUND(__VisualAge, > <=12345) > template struct enable_if; > #else > template struct enable_if; > #endif > > I already explained the reason: C++ compiler vendors use Boost with > BOOST_NO_CONFIG for conformance testing. I'd rather see broken compilers > get fixed than developers forever spending time finding workarounds. OK, agreed. Given that we use another approach for static constants, what do you think about: template< BOOST_UNUSED_TEMPLATE_PARAMETER( bool, cond ), BOOST_UNUSED_TEMPLATE_PARAMETER( typename, T ) > struct enable_if; Or should we instead replace BOOST_STATIC_CONSTANT by a #ifdef, too? Or is BOOST_STATIC_CONSTANT different, probably because there is no "right" code and a workaround, but there are two equally good ways to declare static constants? Regards, Daniel -- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: [EMAIL PROTECTED], web: http://www.aixigo.de ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
> So you would prefer > > #if BOOST_WORKAROUND(__HP_aCC, <= 33900) > template struct enable_if; > #elif BOOST_WORKAROUND(__VisualAge, <= 12345) // Dummy values > template struct enable_if; > #else > template struct enable_if; > #endif > > over > > template struct enable_if; > > If that is the case, then we disagree. Do you have any reason to prefer > the first version? No, I would prefer #if BOOST_WORKAROUND(__HP_aCC, <=33900) || BOOST_WORKAROUND(__VisualAge, <=12345) template struct enable_if; #else template struct enable_if; #endif I already explained the reason: C++ compiler vendors use Boost with BOOST_NO_CONFIG for conformance testing. I'd rather see broken compilers get fixed than developers forever spending time finding workarounds. Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Dave Gomboc wrote: > > > See also the discussion about a "general coding guideline" to "always > > provide a name for template parameters". Here, the maintainer already > > did the right thing when he received the patch. > > If the maintainer hid the compiler brokenness completely, then they did > the wrong thing. If they didn't, they used an #ifdef (via > BOOST_WORKAROUND). So you would prefer #if BOOST_WORKAROUND(__HP_aCC, <= 33900) template struct enable_if; #elif BOOST_WORKAROUND(__VisualAge, <= 12345) // Dummy values template struct enable_if; #else template struct enable_if; #endif over template struct enable_if; If that is the case, then we disagree. Do you have any reason to prefer the first version? Regards, Daniel -- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: [EMAIL PROTECTED], web: http://www.aixigo.de ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
> See also the discussion about a "general coding guideline" to "always > provide a name for template parameters". Here, the maintainer already > did the right thing when he received the patch. If the maintainer hid the compiler brokenness completely, then they did the wrong thing. If they didn't, they used an #ifdef (via BOOST_WORKAROUND). Dave ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Gennaro Prota <[EMAIL PROTECTED]> writes: > #include "boost/type_traits/detail/bool_trait_def.hpp" > > > I end up including: > > - template_arity_spec.hpp > - bool_c.hpp > and > - lambda_support.hpp" (!!!) > > And lambda_support, in turn, includes so much preprocessor stuff that > I think it is more than what I would have in the whole application > hadn't I included is_integral. So why should I use it? After all I can > write the same in portable C++. And, by portable I mean effectively > portable even to broken compilers (the ones I use, of course). Whether these dependencies are worthwhile really depends on whether you think it's valuable to have the boost type traits work out-of-the-box with MPL lambda expressions on broken compilers. If you don't, and you're really worried about every file that gets #included, I agree you'd probably prefer to write your own is_integral. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Gennaro Prota <[EMAIL PROTECTED]> writes: > And lambda_support, in turn, includes so much preprocessor stuff that > I think it is more than what I would have in the whole application > hadn't I included is_integral. Only on non-conforming compilers like vc6/7. On the rest, lambda_support.hpp is essentially empty. -- Dave Abrahams Boost Consulting www.boost-consulting.com ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Gennaro Prota wrote: > > More generally, cleaning up implementations is IMHO a "must do" at > this point of the boost evolution. Rather than worrying about ordinary > releases, I think we should have the library undergoing a global > review, focused on eliminating the noise that have been accumulating > over the years, and the existence of ad hoc solutions in each library > for things that could be factored out in an autonomous component (e.g. > is_signed and related stuff in numeric_traits). Also, I hate the > enormous degree of coupling of most type_traits components: let's say > I include boost/type_traits/is_integral, which should be the most > simple thing in the world to implement. Well, under the appearance of > an innocent: > > #include "boost/type_traits/detail/bool_trait_def.hpp" > > I end up including: > > - template_arity_spec.hpp > - bool_c.hpp > and > - lambda_support.hpp" (!!!) > > And lambda_support, in turn, includes so much preprocessor stuff that > I think it is more than what I would have in the whole application > hadn't I included is_integral. So why should I use it? After all I can > write the same in portable C++. And, by portable I mean effectively > portable even to broken compilers (the ones I use, of course). You managed to express what I always felt but couldn't write down. Thank you for this fine analysis of the situation. > What to say? Just that I expect someone to be hurt by these words and > reply with a biting tone. Probably something along the lines of: if > you have something better then propose it! I know, in any case, c'est > la vie... :-) I doubt that you hurt anyone. If someone did so, it was me. Sorry again :) Regards, Daniel -- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: [EMAIL PROTECTED], web: http://www.aixigo.de ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Sun, 16 Feb 2003 03:12:13 +0100, Daniel Frey <[EMAIL PROTECTED]> wrote: >On Sun, 16 Feb 2003 01:14:17 +0100, David Abrahams wrote: > >> Daniel Frey <[EMAIL PROTECTED]> writes: >> >>> I won't try to fix any of these anymore. I neither understand the >>> documentation nor the implementation of boost's type-traits. I tried to >>> make the code better but AFAICS there is no interest in improvment. >> >> Does anyone understand what improvement you're trying to make? > >I have the impression that the type-traits can and should be improved. I >don't have a complete solution for everything at once and I prefer >evolution over revolution. Thus I tried to start by suggesting a new >is_class implementation. I was disappointed to see only bashing on details >instead of a discussion of the "big picture". > >The basic point was (IMHO) never answered. I tried to clean up the >implementation by providing a closed implementation of is_class for more >compilers. This should decrease the coupling of all the different parts. I >think that this is a better design than the current one. The example I >gave which I thought might show the local problem was wrong. My fault, >granted. But does it speak against cleaning up the code? > >As far as I learned right now, boost is not meant to provide a clean >implementation, instead, it provides a good documentation and an >implementation that "just works". But even the documentation confused me >several times. is_scalar doesn't mention enum, is_member_function_pointer >is not a secondary type category, the mixture of utility functions and a >framework and primary type categories are implemented using secondary >type categories. Even if it works, it is IMHO still bad code. My only >chance to understand type-traits was to create my own implementation from >scratch. But maybe it's just me... Well, I have not been following this thread closely, so my apologies if I'm taking this comment out of context, however having felt more-or-less the same about type_traits I think it is right to back up Daniel in his opinion. The few times I've looked at it, the documentation was more an obstacle than a help; the easiest way to understand the purpose was to look at the code. One of the issues is terminology. For instance what does it mean: ::boost::is_union::value Evaluates to true only if T is of union type. Currently requires some kind of compiler support, ->> otherwise unions are identified as classes. <<-- ? First of all, unions *are* classes to the standard (Well, I think this is just a terminology mistake. However the standard terminology is a reference for a C++ programmer, so if the docs adopt a different convention they should say so). Secondly, the sentence above is in the description of is_union<>, not is_class<>, and it's rather is_class that detects unions; and not "otherwise": it detects unions anyway! :-) As to the point of providing an implementation that "just works", I totally disagree. And I don't think this is the (stated) intent, otherwise I wouldn't use boost at all, and probably wouldn't even be subscribed to the list (if not to keep informed about what is going to be put in the standard). More generally, cleaning up implementations is IMHO a "must do" at this point of the boost evolution. Rather than worrying about ordinary releases, I think we should have the library undergoing a global review, focused on eliminating the noise that have been accumulating over the years, and the existence of ad hoc solutions in each library for things that could be factored out in an autonomous component (e.g. is_signed and related stuff in numeric_traits). Also, I hate the enormous degree of coupling of most type_traits components: let's say I include boost/type_traits/is_integral, which should be the most simple thing in the world to implement. Well, under the appearance of an innocent: #include "boost/type_traits/detail/bool_trait_def.hpp" I end up including: - template_arity_spec.hpp - bool_c.hpp and - lambda_support.hpp" (!!!) And lambda_support, in turn, includes so much preprocessor stuff that I think it is more than what I would have in the whole application hadn't I included is_integral. So why should I use it? After all I can write the same in portable C++. And, by portable I mean effectively portable even to broken compilers (the ones I use, of course). As to your impression, I know the feeling. BTW, I think that's partly due to a couple of reasons: first of all people tend to reply for disagreement more easily than for support, and that's in part logical because otherwise we would have a lot of replies which just said "yes", "yes" and "I agree" :-) Another point is that most people expect "approval" to come from one of the authoritative boost members (Beman, Dave, Peter, etc.). Speaking for myself, even if I agree with a change that you propose, I don't feel to reply with, let's say, a "yes, let's do it", because I don't feel to have the weight to
Re: [boost] Re: is_class
> After thinking about it longer, I still think that there is a problem. The > code seems "twisted" to me. Let me try to explain it, I start by some > observations (all for the case of > BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION not being set): > > is_scalar is based on 3.9/10, which says that enums are scalars. > Currently, is_scalar doesn't detect enums. Oh yes it does :-) template struct is_scalar_impl { BOOST_STATIC_CONSTANT(bool, value = (::boost::type_traits::ice_or< ::boost::is_arithmetic::value, ::boost::is_enum::value, ::boost::is_pointer::value, ::boost::is_member_pointer::value >::value)); }; > is_class needs is_scalar Oh no it doesn't :-) > is_enum needs is_class or it will detect classes which are convertible to > int as enums. Oh no it doesn't :-) still smilingly yours ;-) John Maddock http://ourworld.compuserve.com/homepages/john_maddock/index.htm ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Friday, February 14, 2003, at 06:33 PM, Daniel Frey wrote: A last general question: It seems to me that the boost type-traits are a mixture of two very different concepts: One concept is that of a classic "utility library". This means, that it provides things I can use when I like, but they don't affect my code in general. The other concept is that of a "framework". In order to use is_union, has_* and some other functions, I have to flag my classes, that means I have to write my code in a "boost-friendly" way in order to make it work. I think that it might be worth to make a very clear distinction between these two parts. Comments? In my opinion, the intent from day one was to view the type traits lib as a utility library, and not a framework. The fact that we couldn't make is_union work was viewed as a failure in the implementation that would probably need compiler support to make it work right. Having you specialize your class for is_union was viewed as a workaround for the failing of the implementation, not as a well designed interface. I agree with you that this is an important distinction to make. As proposed to the standards committee, the interface needs to be very clear. -Howard ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Fri, 07 Feb 2003 12:48:13 +0100, John Maddock wrote: >>Why can't I see them?? Look at: > > OK the implementation is: > > BOOST_STATIC_CONSTANT(bool, value = > (::boost::type_traits::ice_and< > ::boost::type_traits::ice_not< ::boost::is_union::value > >::value, ::boost::type_traits::ice_not< > ::boost::is_scalar::value >>::value, > ::boost::type_traits::ice_not< ::boost::is_array::value > >::value, ::boost::type_traits::ice_not< > ::boost::is_reference::value>::value, > ::boost::type_traits::ice_not< ::boost::is_void::value > >::value, ::boost::type_traits::ice_not< > ::boost::is_function::value >>::value > >::value)); > > Note the is_scalar: this takes care of int's floats, pointers and member > pointers. After thinking about it longer, I still think that there is a problem. The code seems "twisted" to me. Let me try to explain it, I start by some observations (all for the case of BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION not being set): is_scalar is based on 3.9/10, which says that enums are scalars. Currently, is_scalar doesn't detect enums. is_class needs is_scalar is_enum needs is_class or it will detect classes which are convertible to int as enums. I think we should still consider that we try to provide a conforming is_class implementation for as much compilers as possible. We should also consider to fix is_scalar. There are some further problems, e.g. is_class< int( int ) >::value fails to compile instead of giving me 'false'. I have to find a solution, but it surely exists. A last general question: It seems to me that the boost type-traits are a mixture of two very different concepts: One concept is that of a classic "utility library". This means, that it provides things I can use when I like, but they don't affect my code in general. The other concept is that of a "framework". In order to use is_union, has_* and some other functions, I have to flag my classes, that means I have to write my code in a "boost-friendly" way in order to make it work. I think that it might be worth to make a very clear distinction between these two parts. Comments? Regards, Daniel ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Wed, 05 Feb 2003 14:37:34 +0100, Daniel Frey <[EMAIL PROTECTED]> wrote: >Maybe it's just me but the boost source is feeling more >and more unmaintainable given the extrem use of MACROs to workaround >each and every problem some compilers have. Am I the only one who feels >uncomfortable with it? No, you are not the only one. Conditionals are also sometimes abused. Another scourge is the "#include the world" problem: sometimes, for instance, just one or two of the type traits are needed and you find #include (removed now, AFAICS from the CVS). Now, I'm not pointing out the oversight, all the more so because Dave has corrected it, but that include, alone, inflates the include tree by 764 entries. That's the case for other boost headers as well. So think about what harms it is when you use them light-heartedly. Genny. begin 644 IncludeTree.zip M4$L#!!0(``J-1B[2>/%@7!8``+L_`@`/26YC;'5D951R964N='AT M[5U1;]NXTGU?8/]#@._Y%FVGV_OJK2:R$ MEDEI9BB*H\6E,TM6D^/!V/-_^ZV91EW=P\ M?_CTX?;;AX]_WOS[Z73S_V9S\_'+S:>O?]Y^_//SMYO;CQ]7O__V^V^-J9L/ M^9\WN^)@;FYO_J\XY+O3UKS>X_[UW^U5([__=M-B^&^Z>_[AOFE>'AZ*Q_>; M]6_X_OON1E^&;G1_JDU%N-OJT^#=:K,S>;/.R_VQV)EJ369[]Q%S_[K9[HJ- M\^[N%KP7GIO]9#WM[Z>FV!7-K[_&;FK3_H:A?=QES4-9[0G$K38^KP;;Z&Y^ M_[,XK&ZI]_XZS/_T\%#\?7U/]WVM/^]ZC?56O^^*?=O9/SS]Y>X2_A%A/>/O M>5:W';<9>$?>^UR0J9NJ.#S^-6R6_U;6:/A>E/7#SZWC5OC;W=H6>JG1[KFZ ML'9K_L[-L?_<>'>^L^Z<[1[+JFB>]B-WQM_]XFWGS:^C0=P:@+K]''BBKGW=^=V^_VB]-0]A%`'DYCK*GJ[LNH?9 M@R8QZZP-#+_6]='DX;P!O'9'#&BON<].?Z_[EY,C@`]!K&\]X_B-];$RQZK, M35V7U?TQJ[)]P,#N@](BEG"G6JV[3$<80&EUA/04?L$&YWEZNNW%57D6Z$3[ M&&O)D3WY+WE]]%,^R[`AY8;PB] MMT5JF?,< M\5$]VX12I3L7)#37X2#(HVBN0T,8[11Z,HQQZH`>QE[#)<']2HV5GM#4M^58 M%H>F/U%)!;(!0ABOS+X='.VX>#"5.>0F7J]SM40@NJG*'^;P/B\;/T#Y6NQ( M1\YV.,\QHDP"<"BE$TT`K@N4()P`O+93BR=`$',YQ>)EB"A`&&MIE1%Q8@K` M]2:S"BH`PU'[EBU%E5<`7V,>3<-2@9J$APPM3<)I"*.M23@58>PU":?ZX)5G M/5+44.%IR'93"%I@T$2Y+KH)0I);U'-DXOU6")6,V*/"0^T6GT6VO]A-&?4! MY"8UB]0L,HRZ9I%I.A[OQR422/<7G_$3(B'I1`">TGZQDSB2+M M-X1*N38I&ZN*_[8^F MC.,`1J."[EMAIL PROTECTED]',.I:K>U.MC.:%,ZS#>'HWD;R*L8W*! M3$-8MN0"CX^$#,J%(&O29E4NA)F32GZX$&:)A.S+A3"K$KA?`->+S;FFJ@\V M9REC@&U`Y"5/+OBX7L?HE8?=L(432G0;`[1[$@VQ>+N]J,ZS73;Q-G4=4,W2 M%"7XF*>]:8H$P_"J>1KUKM"1QEGW""04QQV(3.4)Y0Y:0N*B'/DQ#Y["*(@G7O5=#]]D MW<+K2:2+6!XGR0(VR"*9XC7,I(4%Y06+UC#+!,[N2!>K;-X+6H?B-R*12/7Q M]45TWTFGR53J@`'7,]VX8J`YG/9)GGC7,('NA)OH#8%`&I$!I%]-T">-R+WZ MF_0DYXSX#K.]JG4@;?1LBDWH;@9CP'.@J^E?!M:;K^$WPHSP!4W[XL2%!@_Q MM-LX#H%,1^<8=(XA!L+,TCD&G6,@@.OU=(YA0K`-D3G'X`G]JU0;2PYAP(R^ M\D5\%9DP;^ZQO<5/B5QW+ZV!4\'CI#5PK8&S$6:-UL`C@.O=M`8^`=A&R*N! M]Y4'YH,CN>5O7&EVDM-1AX!KFU:SWYO]QE3QN0-(-`AF)$X6_-QQE>;S]0^G M0P[1:9YW`>!Q$O9B`&&&X`NZK_>#FW7W61=MI(AO((#/K3,TT>*G#D%OZ1:1 MNR8JNP/(E!94>@?PN$DOOP."+)-;@@>$F2:Q#`\(LTIZ*1X09F'B'<;,6)7ZXO4O7'.B:@TD19I:N M.=`U!P1PO9ZN.9@0;$-DKCGP1O]OK%T-TJTZ<*@QVM>-V2'M;J06A\X`>=\W M.IXR_D-8L/!0IIW.LC@LZBDCRL6B"`M-'LA4%I(X\#A)3AJ"+-)U--*MT74T M$<#U;KJ.9@*PC9"WCL:A/U:(+Z=F30<&Z%\OI<%],#C'JA02;<(:@8C;LY`H M>V1?S,Y,X>?S&`EE*==OZ#$B<\G1(&OT&!&IEN@Q(A."Z\7T&)$`L`V0=8S( M592^DS2-/D"\=Y!(^MWT\%P1BCA6;\"3M,3DQ,=/VD#S4?&HXI&,(&M4/*IX MI"',*A6/:+`YJWBDP\?U6C+P8O3,TG'X7&/<)W3MXZXC]0Y,JR-D$W6&*WKX M"FK^?/Y!Y(^KR#26\:1Y^Z&K-B:"QT>UL6IC$L(L46T\(;A>3+5Q`-@&R-+& M5W+HDZ19?!^!876,VQ7CN6Q'/JT=D_`/$)^U;IRA?E/&(IU])RN.-_XHHVL=E/.(( M)3?W^HI!PC[_D4A%<]V@5`7-XR)1/0=9(DLYAYFR$,6P0,4<9E$"M?++'5URINIRTZ,QCL3$`='V#HNF@D`!@&"&>]+:,6PQG?SE,5*#WG$ M^H24&8>'M:S=FL@4M/JGU3\JPDS1ZI]6_\[@>BNM_C'`)B^P^N>.Q7=2ILF' M3!B1SUH'U#J@#T%6:!UP.H19H'7``'"]DM8!"6`3%U8'=,?8A10#?3W6;^SQ M5XI'_-HJN_PW-6D`I65:P2_>US$Q&$[U@UTV1E7ZZXO'Y%6N_U@<=#Z[T"S=!Z[S@_&L*LT7JO%VRN6N\=AX_C M0'!=2J$7442PK=R:=(L^+]MF%GUC&0"@MT\K`";M*Z MW%,+?A@$6:(%O^D19H46_"8`UUMIP8\!-GF!!3]G*%[4:D^WF-#BGQ;_?`BR M0HM_TR',`BW^!8#KE;3X1P";N+#BGS/$+J4$B-A#SA9$[Q^XS\90PG?=")J( M]QUO_2F"'Z+H%;M4BF")._4=8L33WC3%A.X400ZQLO&%7)7-M![:;HU0F)W3 M43HHVH$GTAFA%#8L1ZV%521X7+2PJH754819H875"<#U5EI898!-7DAAU1%\ MOPI?06D_1<0$;&OA)JL-?$'4OH-629L9Y^P]C7>A%+?*(-^U&=Z\W==NE4`V MA5MS4<5UB],A2>"P6R8D")79MW%OG3_'8PQ`-4^@O:G*'^;0IM;[8[$S561E M"R!9@/\*<:Z#;0$D$SSN.N98[$#B:0W*2!EF'Q1ZA(_WWG\4+^7L@TQ)>`K: M!X^;Q)2TCR#+Y!V19B/,-$G'I=D(LTKJT6DVPBQ,=(R:#:XW'!U.<_V*!)/V+KZX&9*'TR%/=_IXCT`W!'$KDV;H'P`B=WS.\Y#M:@,"YK1+'W;Z M9#IS/+XE<=!Q/7B/WY;'E'#0L76#];&IUD]F=S01HTX'-BV"AQ?X8O#)_4;K M%9.!QTOK%5JOF`1A%FF](B*X7D_K%1.";8C,>H4C[O^!GQ[:2"Q9$-;\1]L0 MO`.%-FT?\RA;:W>@T):I$KG#5+I"Y'&2K`Z#+)*I#,-,6EC$6[`B#+,LH1KD M>K?42I#-6]*88!N12`'Z^#J"^3=ILU4#W(<^A\"=8-,^^-;K-,4FQL$[`"9[ M`0?:`)CL$ZPB9S*5IURYKD6R:N7QD:I8@ZR1IU;#S%E05%ZH2@VS*I%"Y7JQ ME.J4S7DAW\O[#4B@2GUPUO>?H=D M&IH1:484@C!S-"/2C,@!KA?3C"@`;`-D943N4"WFT'.`AX`MFG$KTF!EUV,5 M0S$C*))6H;UO'Q5K.=HX8TP?F&'='((H;N:UW/S'Y#,?UG71+"U12C>3AP`M@&RTN.K*/V9M:PG669\AUOU>2PCQ"D$ M.UPJE#*WQ*4^$9,U!$=3DC]#ME_R/\W]/YB2.4,@V\:V1]=PE[[WB M)(P;G6\+A],3QJ^B2S5=Y*2=X/PI(D7"P5,;34[9X/'1Y%234Q+"+-'D=$)P MO9@FIP%@&R`L.74$:DQ&)2E#Q:U.C+2_'X(?;FEBG.5=X_0^X]8A/I>MXRO2 M[%J"V:KFO/'#!G:YF3GUN6IZ),E/,=2]'*U$_GM>-]MV$/\UK\?T4L.[H?M*5=&OTI*L(X'JWT>&26
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] Re: is_class
Peter Dimov wrote: > > From: "Daniel Frey" <[EMAIL PROTECTED]> > > Peter Dimov wrote: > > > > > > Are you sure that "T C::* const" is a type? > > > > Isn't it? It's a constant pointer to a member of class C. T may be the > > type of a member variable or (although GCC don't detect it) a function > > type. At least this is my current understanding. Do you have a reason to > > ask about it? I think so, but I can't see it... > > 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; To create something that matches to above specialization, you have to do something like this: ft X::* const cpf; 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? Regards, Daniel -- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: [EMAIL PROTECTED], web: http://www.aixigo.de ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
From: "Daniel Frey" <[EMAIL PROTECTED]> > Peter Dimov wrote: > > > > Are you sure that "T C::* const" is a type? > > Isn't it? It's a constant pointer to a member of class C. T may be the > type of a member variable or (although GCC don't detect it) a function > type. At least this is my current understanding. Do you have a reason to > ask about it? I think so, but I can't see it... Yes, I worded that incorrectly. I should have said: are you thinking that the above will match int (X::*pf)(long, double) const; ? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
Peter Dimov wrote: > > Are you sure that "T C::* const" is a type? Isn't it? It's a constant pointer to a member of class C. T may be the type of a member variable or (although GCC don't detect it) a function type. At least this is my current understanding. Do you have a reason to ask about it? I think so, but I can't see it... Regards, Daniel -- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: [EMAIL PROTECTED], web: http://www.aixigo.de ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: is_class
From: "Daniel Frey" <[EMAIL PROTECTED]> > On Tue, 04 Feb 2003 00:23:26 +0100, Paul Mensonides wrote: > > > - 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. > > And which is exactly the kind of type-deduction that the GCC fails to do > - which is why I needed to create the slightly more complex version to tame > both compilers at the same time :) Are you sure that "T C::* const" is a type? ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
[boost] Re: is_class
On Tue, 04 Feb 2003 00:23:26 +0100, Paul Mensonides wrote: > - 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. And which is exactly the kind of type-deduction that the GCC fails to do - which is why I needed to create the slightly more complex version to tame both compilers at the same time :) Regards, Daniel ___ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost