Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent zero in a template parameter?

Tags:

c++

templates

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?

like image 691
Arseni Mourzenko Avatar asked Jul 11 '21 21:07

Arseni Mourzenko


People also ask

What is correct for template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

How will you restrict the template for a specific datatype?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.

What is the role of parameter in a template?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

How do I parameterize a template?

Every template is parameterized by one or more template parameters, indicated in the parameter-list of the template declaration syntax: template < parameter-list > declaration Each parameter in parameter-list may be: a non-type template parameter;

What is a template argument for a template parameter?

A template argument for a type template parameter must be a type-id, which may name an incomplete type: A template argument for a template template parameter must be an id-expression which names a class template or a template alias. When the argument is a class template, only the primary template is considered when matching the parameter.

When is a non-type template parameter unmodifiable?

When the name of a non-type template parameter is used in an expression within the body of the class template, it is an unmodifiable prvalue unless its type was an lvalue reference type, or unless its type is a class type (since C++20) .

What is a default template parameter in C++?

If the default is specified for a template parameter of a primary class template , primary variable template, (since C++14)or alias template, each subsequent template parameter must have a default argument, except the very last one may be a template parameter pack.


Video Answer


4 Answers

The C++20 way is

template <typename T, size_t S> requires (S > 0)
class Example
{
    // ...
};
like image 115
HolyBlackCat Avatar answered Oct 23 '22 09:10

HolyBlackCat


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.

like image 45
Sam Varshavchik Avatar answered Oct 23 '22 11:10

Sam Varshavchik


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.

like image 21
eerorika Avatar answered Oct 23 '22 09:10

eerorika


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.

like image 31
Martin York Avatar answered Oct 23 '22 11:10

Martin York