davetapley
davetapley

Reputation: 17968

Casting to int or float depending on is_integer

I have some type T, and in some cases it may be, for example char, but I want to output its integral value, not the character. For this is have the following:

typedef ( std::numeric_limits< T >::is_integer ? int : float ) FormatType;
os << static_cast< FormatType >( t );

However this fails to compile, stating "error C2275: 'int' : illegal use of this type as an expression". Prefixing int and float with typename does not revolve the issue. What am I missing here?

The following, which I believe is equivalent, works:

if( std::numeric_limits< T >::is_integer )
{
    os << static_cast< int >( t );
}
else
{
    os << static_cast< float >( t );
}

Upvotes: 2

Views: 347

Answers (3)

justin
justin

Reputation: 104698

gcc accepts it, not sure about others:

template<bool Expression, typename TrueResult, typename FalseResult>
  class conditional_type;

template<typename TrueResult, typename FalseResult>
class conditional_type<1, TrueResult, FalseResult> {
public:
    typedef TrueResult R;
};

template<typename TrueResult, typename FalseResult>
class conditional_type<0, TrueResult, FalseResult> {
public:
    typedef FalseResult R;
};

typedef conditional_type<std::numeric_limits<T>::is_integer,int,float>::R FormatType;

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545865

What am I missing here?

You are trying to use types as expressions. C++ simply doesn’t allow this. You can instead use so-called “compile-time if” via metaprogramming. For example, I believe Boost offers the following:

typedef if_<std::numeric_limits< T >::is_integer, int, double>::type FormatType;

os << static_cast< FormatType >( t );

On your other hand, your second solution works well, and the compiler will figure out that one of the branches can never be true, and eliminate it. So the performance will be the same in both cases (in fact, the exact same code should be generated).

Upvotes: 3

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385274

Try using integral promotion:

os << +t;

You'll get an int out of it for an integral type, or your original floating-point type if it was one.

Upvotes: 2

Related Questions