Reputation: 113
The following code snippet was taken from folly, checking whether one integer is greater than the other in compile time.
#include <limits>
#include <type_traits>
template <typename RHS, RHS rhs, typename LHS>
bool greater_than_impl(
typename std::enable_if<
(rhs <= std::numeric_limits<LHS>::max()
&& rhs >= std::numeric_limits<LHS>::min()),
LHS
>::type const lhs
) {
return lhs > rhs;
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than_impl(
typename std::enable_if<
(rhs > std::numeric_limits<LHS>::max()),
LHS
>::type const
) {
return false;
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than_impl(
typename std::enable_if<
(rhs < std::numeric_limits<LHS>::min()),
LHS
>::type const
) {
return true;
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than(LHS const lhs) {
return greater_than_impl<
RHS, rhs, typename std::remove_reference<LHS>::type
>(lhs);
}
int test()
{
auto v = greater_than<int, 0, int>(0);
std::cout << v << std::endl;
return 0;
}
GCC 4.8.2 show me the expected compiling result, but Visual C++ 2013 gives me an error at the second template function greater_than_impl
:
C2995: function template has already been defined
seems that std::enable_if overloading was not recognized, is Visual C++ 2013 lack of any SFINAE feature?
Upvotes: 3
Views: 1004
Reputation:
VC++ 2013 doesn't support constexpr. And from what I can tell they implement max
and min
as non-const static
functions. You can't use them where constant expressions are required, i.e.:
#include <limits>
#include <array>
int main()
{
std::array<int, std::numeric_limits<int>::max()> a;
}
error C2975: '_Size' : invalid template argument for 'std::array', expected compile-time constant expression
As a workaround, I've tried to copy libstdc++'s implementation of numeric_limits
, something like the following:
struct wrapper_base
{
// member variables
};
template <typename T>
struct wrapper : public wrapper_base
{
static const T max()
{
return T();
}
static const T min()
{
return T();
}
};
template <>
struct wrapper<int>
{
static const int max()
{
return INT_MAX;
}
static const int min()
{
return INT_MIN;
}
};
Unfortunately, this gives the same function template redefinition error. You can use INT_MAX
and INT_MIN
directly, but that would require specializing for 16 types (in libstdc++'s case.) It's better to probably avoid this approach altogether and follow Praetorian's advice.
Upvotes: 2