Home > database >  C Fixed Range Int
C Fixed Range Int

Time:08-28

I'd like to create a type with a compile-time guarantee that instances are one of N possible values. The values are int types. No arithmetic needed.

One possible solution is to use an enum class, but this scales poorly with N.

I think the solution would look most like a fixed range int. I imagine the usage would look something like this, but i'm not too sure how to implement this.Is something like this possible or am I limited to enum classes?

constexpr auto N = 60;
MyType<N> foo(30); // okay
MyType<N> foo(0); // okay
MyType<N> foo(59); // okay
MyType<N> bar(60); // compile error
MyType<N> boo(-1); // compile error

CodePudding user response:

I don't think it's possible to get compile error, however you can limit it using custom class something like this:

#include <stdexcept>

class MyIntger {
public:
  MyIntger(int num){
    if(num < Min || num > Max){
      throw std::runtime_error("Number out of range");
    }
    value = num;
  }

private:
  int value;
  const static int Min = 0;
  const static int Max = 60;
};
int main(){
  MyIntger a(5);    // OK
  MyIntger b(61);   // Throws std::runtime_error
}

CodePudding user response:

You can have compile-time ints in C (and thus compile-time limit checking), but syntax is not the same as for runtime ints:

#include <type_traits>

template<size_t N>
struct MyInteger
{
    // you might have it as T or limit it to size_t
    template<typename T, T I>
    MyInteger(std::integral_constant<T, I>)
    : value(I) { static_assert(I < N); }

    size_t value;
};

int main()
{
    MyInteger<60> a(std::integral_constant<size_t, 59>()); // ok

    MyInteger<60> b(std::integral_constant<size_t, 60>()); // error
}

If you don't like the long name, you can always have a template type alias, e.g.:

template<size_t K>
std::integral_constant<size_t, K> I = {};

int main()
{
    MyInteger<60> a(I<59>);
}
  • Related