1

I have a function that we use to enforce type matches when setting into a buffer:

void SetUInt8(size_checker<uint8_t> val)
{
     // make some static checks
}

usually, it is invoked like this:

// compile error, since you might mean to call the SetUInt() function
int myvar = 10;
SetUInt8(myvar);      

// works fine
int8_t myvar = 1;
SetUInt8(myvar);

This call causes a warning because the 30 is interpreted as an int:

SetUInt8(30);

But I really want this to be OK since 30 < 256. Ideally, I would like the invocation not to have to change, but I have come up with the following:

template<size_t T>
void SetUInt8()
{
    ASSERT(T < 256);
    // do other stuff
}

Which of course would be used like:

SetUInt8<30>();

Alternatively, I can cast when calling the function:

SetUInt8(uint8_t(30U));

Is there another way around the issue of 30 being converted to an int, or detecting its actual value if its a compile time constant?

JaredC
  • 5,150
  • 1
  • 20
  • 45
  • 1
    possible duplicate of [Checking at compile time if specified value is in a range of a type](http://stackoverflow.com/q/5556466/636019) – ildjarn May 26 '11 at 18:39
  • @ildjarn: That range-checks a non-type template argument; this is certainly different (and harder). – MSalters May 27 '11 at 08:00
  • @MSalter : I don't see why an overload can't be provided for literals (which are what's causing the warnings), which does the range check then delegates its actual work to the existing overload... – ildjarn May 27 '11 at 13:35
  • @ildjarn: C++ doesn't have overloading on literals. – MSalters May 27 '11 at 13:53
  • @MSalters : I meant `SetUInt8<30>();` vs. `SetUInt8(30);` (sorry, thought this was obvious). – ildjarn May 27 '11 at 13:55
  • @ildjarn: Well, that's technically not an overload. If you stick to the `SetUInt8(30);` call syntax, the question would require a real overload of `SetUInt8` that's selected because the argument (`30U`) is a literal. Well, such overloading just doesn't exist in C++. – MSalters May 27 '11 at 14:00
  • @MSalters : I'm not suggesting sticking to the `SetUInt8(30);` call syntax, I'm suggesting having a different syntax for literals. – ildjarn May 27 '11 at 14:09
  • Certainly a different syntax is possible (as I mention). My goal is to avoid that. Code would be much cleaner if all calls could be `SetUInt8(blah)`. Looks like I may have to give up on my hopes.... – JaredC May 27 '11 at 19:11

1 Answers1

2

The best thought I have is a template, static-asserted function that static_casts for you:

template<size_t size>
void SetUInt8()
{
    BOOST_STATIC_ASSERT(size < 256);
    SetUInt8(static_cast<uint8_t>(size));
}

Call it like you did: SetUInt8<50>();

Since it should hopefully always be inlined there's no performance overhead and it does compile-time range checking. Better would be if the compiler were smart enough to not warn when the value clearly fits in the range of the smaller type.

Mark B
  • 95,107
  • 10
  • 109
  • 188