问题
Is there a way that I can use std::numeric_limits<T>::is_integer
and std::numeric_limits<T>::is_specialized
to change template behavior?
For example can I do this:
template < typename T >
void foo( const T& bar )
{
if( std::numeric_limits< T >::is_integer )
{
isInt( bar );
}
else if( std::numeric_limits< T >::is_specialized )
{
isFloat( bar );
}
else
{
isString( bar );
}
}
回答1:
The "obvious" answer is that you could use something like std::enable_if
.
For example:
template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, void>::type
foo(const T &bar) { isInt(bar); }
template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_specialized, void>::type
foo(const T &bar) { isFloat(bar); }
The problem with this approach is that this is ambiguous for (as an example) an int
parameter, since numeric_limits<int>::is_specialized == true.
To resolve this, I would simply use a better trait than numeric_limits
, personally. You can also use boolean conditions to test for the exact condition you want:
template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_integer, void>::type
foo(const T &bar) { isFloat(bar); }
回答2:
What you have is currently valid. However, you should prefer to use SFINAE and <type_traits> instead since it would dispatch to a different function based on the type rather than rely on a branch condition (which may or may not be optimised away).
You can use std::enable_if to do the following:
template<typename T,
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& t) {
isInt(t);
}
template<typename T,
typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
void foo(const T& t) {
isFloat(t);
}
template<typename T,
typename std::enable_if<!std::is_integral<T>::value &&
!std::is_floating_point<T>::value, int>::type = 0>
void foo(const T& t) {
isString(t);
}
Live Demo
The reason that the second parameter for enable_if
is set to int
is to save us some typing. If the int
is left out then we'd have to do typename = typename std::enable_if<std::is_integral<T>::value>::type
instead of just setting it to 0
which would save us a couple characters to type. They're equivalent for all intents and purposes.
来源:https://stackoverflow.com/questions/25251380/stdnumeric-limits-as-a-condition