galinette
galinette

Reputation: 9292

Getting the maximum allowed value for a member variable in C++11

I am using an external library which defines a struct with an unsigned int C-style array:

struct Foo
{
    unsigned int bar[8];
}

In my code, I want to get the numeric_limits::max() for that type in order to check out of bounds values, and avoid passing overflowed values to the library.

So I do :

auto n = Foo().bar[0];
if(myBar > std::numeric_limits<decltype (n)>::max())
{
    error("The Foo library doesn't support bars that large");
    return false;
}

This works, but is there a more elegant c++11 way not implying declaring a variable? If I use decltype(Foo().bar[0]) I have an error, as this returns a reference type, which numeric_limits doesn't like.

Upvotes: 1

Views: 288

Answers (3)

Cedric
Cedric

Reputation: 313

You could have something like this :

#include <limits>
#include <type_traits>

struct Foo {
  unsigned int bar[8];
};

int main() {

  auto max_val = std::numeric_limits<std::remove_all_extents_t<decltype(std::declval<Foo>().bar)>>::max();


  return 0;
}

std::remove_all_extents removes the "array part" of your member. The advantage is that this will work on simple int, int [], and multi-dimensional arrays too. As you don't make use of the operator[], you avoid the "reference problem" as well.

std::declval allows to determine the type of bar if you don't have an instance at hand.

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 172864

For lvalue expressions like Foo().bar[0], decltype yields type T&, i.e. lvalue-reference type.

You can remove the reference part by using std::remove_reference.

std::numeric_limits<std::remove_reference<decltype(Foo().bar[0])>::type>

Upvotes: 2

catnip
catnip

Reputation: 25388

As an addendum to @songyuanyao's answer, you can avoid having to instantiate Foo by using std::declval, like so:

if (myBar > std::numeric_limits<std::remove_reference<decltype(std::declval <Foo>().bar [0])>::type>::max())
...

Live demo

Upvotes: 0

Related Questions