Boost logo

Boost :

From: Gennaro Prota (gennaro_prota_at_[hidden])
Date: 2003-02-19 17:41:09


On Wed, 19 Feb 2003 16:09:26 +0200, "Rani Sharoni"
<rani_sharoni_at_[hidden]> wrote:

>> // fire-prevention
>> template <typename T>
>> Burn<T> 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<T> 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 <typename U>
 no check_is_reference (U*); // VC++ fails in some cases with this.
                             // (yeah, it's able to form pointers
                             // to references!!!)
 template <typename U>
 yes check_is_reference (...);

 
 template <typename T>
 struct is_reference {
     
     BOOST_STATIC_CONSTANT(bool, value =
         sizeof(yes) == sizeof (::check_is_reference<T>( 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 <typename T>
 void f(T* p) {
   
 }

 f<int&>(0); // <-- works!

The problem arises when you try to use the pointer, of course.
Example:

 template <typename T>
     T f(T* p) {
        return *p; // (1)
 }

 f<int&>(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 <typename U>
     no check_is_reference (U*);

 template <typename U>
     yes check_is_reference (...);
 
 
 template <typename T>
     struct is_reference {
     
     static T t;
     BOOST_STATIC_CONSTANT(bool, value =
         sizeof(yes) == sizeof (::check_is_reference<T>( &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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk