Re: Dumbed-down
Seungbeom Kim wrote:
> kanze wrote:
>>> Seungbeom Kim posted:
>>>> template <class Target, class Source>
>>>> inline Target numeric_cast(Source x)
>>>> {
>>>> assert( x is in the range of Target );
>>>> return static_cast<Target>(x);
>>>> }
>>>> (I'm not sure how to express in C++ what I wrote inside assert( );
>>> assert( numeric_limits<Target>::max() >= x );
>> assert( std::numeric_limits< Target >::max() >= x
>> && (! std::numeric_limits< Target >::is_signed
>> || (std::numeric_limits< Target >::is_integer
>> ? std::numeric_limits< Target >::min() >= x
>> : -std::numeric_limits< Target >::max() >= x)=
) )
>> ;
> Thanks for your idea.
> But this causes numeric_cast<signed>(1) to fail the assertion,
> because 'std::numeric_limits< Target >::min() >= x' is false.
> You might have meant 'std::numeric_limits< Target >::min() <= x'
Obviously:-).
> but this causes numeric_cast<signed>(1000000000U) to fail the
> assertion (where int is 32 bits).
Or even numeric_cast< signed >( 1U ).
Yuck. You're right. Worse: I'm not sure right off of a good
solution. I suspect that you'd have to do something involving
the signedness of Source as well. (If the first test passes,
and !std::numeric_limits< Source >::is_signed, no further tests
are applicable.)
Note that my expression also fails in the reverse case:
numeric_limits< unsigned >( -1 )
Again, -1 gets converted to unsigned in some of the
comparisons.
The best I can come up with rapidly is:
template< bool condition >
class Discriminator
{
} ;
// Target is_signed, ! is_integer, Source is_signed
template< typename Target, typename Source >
inline bool
isValidLower( Source value, Discriminator< true >, Discriminator<
false > )
{
return -std::numeric_limits< Target >::max() <= value ;
}
// Target is_signed, is_integer, Source is_signed
template< typename Target, typename Source >
inline bool
isValidLower( Source value, Discriminator< true >, Discriminator<
true > )
{
return std::numeric_limits< Target >::min() <= value ;
}
// Target ! is_signed, is_integer, Source is_signed
template< typename Target, typename Source >
inline bool
isValidLower( Source value, Discriminator< false >, Discriminator<
true > )
{
return 0 <= value ;
}
// Source unsigned...
template< typename Target, typename Source >
inline bool
isValid( Source value, Discriminator< false >, Discriminator< false =
)
{
return std::numeric_limits< Target >::max() <= value ;
}
// Source signed
template< typename Target, typename Source >
inline bool
isValid( Source value, Discriminator< true >, Discriminator< false >=
)
{
// Note: this may give a false negative if Target is
// unsigned and value is negative. But in this case,
// the second condition would be sure to fail anyway,
// so the results would still be false.
return std::numeric_limits< Target >::max() <= value
&& isValidLower(
value,
Discriminator< std::numeric_limits< Target >::is_signed
> >(),
Discriminator< std::numeric_limits< Target
>::is_integer> >() ) ;
}
template< typename Target, typename Source >
Target
numeric_cast( Source x )
{
assert(
isValid< Target >( x,
Discriminator< std::numeric_limits< Source
>::is_integer >(),
Discriminator< std::numeric_limits< Target
>::is_integer >() ) ) ;
return static_cast< Target >( x ) ;
}
Untested, but there's got to be a simpler solution.
--
James Kanze kanze.james@neuf.fr
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]