JorenHeit
JorenHeit

Reputation: 3997

C++11 numeric_limits<>::max() at compile time

When I was trying to get something to compile on MSVC, I found out (sigh) that the version used in Visual Studio Express 2013 doesn't support constexpr functions yet. Therefore, I couldn't pass the result of std::numeric_limits<size_t>::max() to a template. I can hack around this by just casting -1 to size_t, but I don't think this would strictly be portable, as (correct me if I'm wrong) the two's complement way of defining negatives isn't standardized (yet).

What is the recommended approach on doing this?

Upvotes: 1

Views: 1372

Answers (2)

bolov
bolov

Reputation: 75727

template <class T, class Enable = std::enable_if_t<std::is_unsigned<T>::value>>
struct NumericLimits {
  static const T sk_min_ = 0;
  static const T sk_max_ = static_cast<T>(-1);
};

usage as a template parameter:

template <class T, T N>
class X{};

template <class T>
class Y {
  // to instantiate X here you need a templated way
  // to get the max value of `T` because you don't know
  // what `T` actually is so you can't use something like INT_MAX
  X<T, NumericLimits<T>::sk_max_> x_;
};

auto y = Y<unsigned long>{};

An unsigned variable is guaranteed by the standard to wrap around. So if you want to use a general way to get the max value of an unsigned type (including as a template argument) the above code will work.

For signed types I don't know if there is a conforming way other than specializing for each type (there are only a few (char, signed char, short, int, long, long long so that is duable too). (and I mean use INT_MAX, not hard coded values as you don't know the range of the implementation)

Please note that I've test it on g++ with c++14 so it might need little tweaks to work on Visual Studio.

Upvotes: 2

joshuanapoli
joshuanapoli

Reputation: 2509

The boost integer library is ported to many platforms and has a max constant: boost::integer_traits<size_t>::const_max.

Upvotes: 4

Related Questions