Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-type template parameters and requires

I am learning concepts, and I can not figure out a way to restrain the value (not type) of non-type template parameter.

Example of code that compiles, although I wish it did not(due to failed requirement):

#include <cassert>

enum Bla{
    Lol, 
    Haha
};

template<Bla b>
requires requires{
    // my guess is that this just checks that this is valid expression, not
    // that it is true
    b>1; 
}
void f(){
    assert(b>1);
}

int main() {
    f<Lol>(); // compiles, not funny ;)
}

Note: this is simplified example( I want "template overloading") so static_assert is not good for me, and I am trying to avoid std::enable_if since syntax is hideous.

like image 522
NoSenseEtAl Avatar asked Nov 16 '20 12:11

NoSenseEtAl


People also ask

Which parameter is allowed for non-type template?

Which parameter is legal for non-type template? Explanation: The following are legal for non-type template parameters:integral or enumeration type, Pointer to object or pointer to function, Reference to object or reference to function, Pointer to member.

What is template type parameter?

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.

Which is correct example of template parameters?

For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.

What is a non-type?

NoneType is the type for the None object, which is an object that indicates no value. None is the return value of functions that "don't return anything".


2 Answers

If you only have a boolean condition and nothing else, do this:

template<Bla b>
requires(b > 1)
void f() {}

Alternative longer syntax, if you need to check more things in the same requires-expression:

template<Bla b>
requires requires
{
    requires b > 1;
//  ^~~~~~~~
}
void f() {}
like image 170
HolyBlackCat Avatar answered Sep 22 '22 20:09

HolyBlackCat


Since f needs to be constrained only by the value of the non-type template parameter, you can simply write a requires clause instead of an ad-hoc requires requires constraint:

template<Bla b>
requires (b>1) 
void f() {}

Here's a demo.

You only need a requires requires expression if you want to do more complicated checks on the template parameter. In that case, I recommend using a named concept over an ad-hoc constraint anyway. This makes the code more readable, and allows you to reuse the concept in other places.


As for assert, it's a run-time construct, so it doesn't affect compilation in any way, assuming the expression inside the assert is syntactically valid. You need to use static_assert instead, if you want to check the template parameter at compile time:

static_assert(b>1);
like image 40
cigien Avatar answered Sep 21 '22 20:09

cigien