[boost] Re: is_class

2003-02-19 Thread Gennaro Prota
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

2003-02-19 Thread Rani Sharoni
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

2003-02-19 Thread Gennaro Prota
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

2003-02-18 Thread Peter Dimov
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

2003-02-18 Thread Rani Sharoni
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

2003-02-17 Thread Daniel Frey
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

2003-02-17 Thread Gennaro Prota
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

2003-02-17 Thread Gennaro Prota
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

2003-02-17 Thread Dave Gomboc
> > 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

2003-02-17 Thread Daniel Frey
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

2003-02-16 Thread Dave Gomboc
> 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

2003-02-16 Thread Daniel Frey
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

2003-02-16 Thread Dave Gomboc
> 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

2003-02-16 Thread David Abrahams
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

2003-02-16 Thread David Abrahams
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

2003-02-16 Thread Daniel Frey
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

2003-02-16 Thread Gennaro Prota
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

2003-02-15 Thread John Maddock
> 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

2003-02-14 Thread Howard Hinnant
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

2003-02-14 Thread Daniel Frey
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

2003-02-06 Thread Gennaro Prota
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

2003-02-04 Thread Paul Mensonides
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

2003-02-04 Thread Daniel Frey
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

2003-02-04 Thread Peter Dimov
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

2003-02-04 Thread Daniel Frey
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

2003-02-04 Thread Peter Dimov
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

2003-02-03 Thread Daniel Frey
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