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 );
}
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).
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.
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;
精彩评论