Arseni Mourzenko
Arseni Mourzenko

Reputation: 52331

How do I prevent zero in a template parameter?

I have a template class where the template parameter corresponds to the size of an array within the class.

template <typename T, size_t S>
class Example {
    ...

 private:
    T values[S];
};

This leads to an expected warning: “ISO C++ forbids zero-size array.” In my case, something like Example<uint8_t, 0> would make no sense, and I would like to prevent the code containing Example<..., 0> from compiling.

How do I express in C++ that S should be superior or equal to one?

Upvotes: 8

Views: 513

Answers (4)

Loki Astari
Loki Astari

Reputation: 264571

If there are situations where S being zero are valid. You can add a specialization for that case.

template<typename T, size_t S>
class Example {
    ...

 private:
    T values[S];
};

template<typename T>
class Example<T, 0> {
    ...
    private:
    // Don't need an array here for this case.
};

This will keep your code compiling in situations where you have heavy templating that makes S zero.

Upvotes: 2

HolyBlackCat
HolyBlackCat

Reputation: 96579

The C++20 way is

template <typename T, size_t S> requires (S > 0)
class Example
{
    // ...
};

Upvotes: 12

Sam Varshavchik
Sam Varshavchik

Reputation: 118445

You're really trading in one compiler diagnostic for another, but here's one approach:

template <typename T, size_t S,
      typename=std::enable_if_t< (S>0) >>

Alternatively: use static_assert to get a friendlier error message:

template <typename T, size_t S>
class Example {

 private:

    static_assert(S>0);
    T values[S];
};

You'll get a friendlier error message however this template will still participate in overload resolution, which in some edge cases may be undesirable.

Upvotes: 8

eerorika
eerorika

Reputation: 238401

T values[0]; is alread ill-formed. Thus, if you configure the compiler to not use language extensions, then it won't compile.

Or, you can use a static_assert.

Upvotes: 4

Related Questions