Boost logo

Boost :

Subject: Re: [boost] review request: addition to type_traits library of has_operator_xxx
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2010-12-09 15:50:15


On 12/9/2010 12:18 PM, Frédéric Bron wrote:
> I made some progress in the implementation of operator traits.
[...]
> 3. I have tried to use the existing is_convertible traits but without
> any success:
> The problem is that is_convertible expect a type as parameter, not an
> expression. So I have tried to get the return type of the operator
> with:
> a) boost result_of (but this does not work for arbitrary expression),
> b)boost typeof (but types must be registered first)
> c) with the following code:
>
> #include<iostream>
> #include<boost/type_traits/is_convertible.hpp>
>
> template<class To, class From>
> bool is_conv(const From&) { return boost::is_convertible< From, To>::value; };

Here, rather than returning a run-time true/false, return a compile-time
true/false. I.e., use the sizeof trick.

template< std::size_t N >
struct sizeof_t
{ char _[N]; };

BOOST_MPL_ASSERT_RELATION( sizeof( sizeof_t<1> ), !=, sizeof(
sizeof_t<2> ) );

template< class To, class From >
sizeof_t< boost::is_convertible< const From&, To >::value + 1 >
is_conv(const From&);

[...]
> but if I use is_conv(1+2) to set a value variable of type bool in the
> traits, the compiler complains that "is_conv(1+2)" is not a constant
> expression...

So now sizeof( is_conv< bool >(1+2) ) == sizeof( sizeof_t<2> ) is a
static constant expression.

It could also be useful to distinguish the const-qualifications of
referents, i.e., add another overload of is_conv:

template< class To, class From >
sizeof_t< boost::is_convertible< From&, To >::value + 1 >
is_conv(From&);

And you can get even fancier if you want to distinguish between lvalues
and rvalues (warning: untested):

template< class From, class T >
struct is_conv_result
{ typedef sizeof_t< boost::is_convertible< From, To >::value + 1 > type; };

template< class To, class From1, class From2 >
typename is_conv_result< From1&, To >::type
is_conv(From1&, From2&); // catches lvalue references-to-non-const

template< class To, class From1, class From2 >
typename is_conv_result< const From1&, To >::type
is_conv(const From1&, From2&); // catches lvalue references-to-const

template< class To, class From >
typename is_conv_result< From, To >::type
is_conv(const From&, ...); // catches rvalues

You just need to pass the expression in question to both parameters of
is_conv.

HTH,

- Jeff


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