Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++20 concept : requires expression and perfect forwarding

FYI: C++17 std::is_invocable_v does exactly what i was expecting.

Imagine a concept to check if the invocation of a callable object is possible with specific argument types:

template <typename Fn, typename... Args>
concept has_request_interface = requires (Fn request, Args&&... args)
{
    { std::invoke(request, std::forward<Args>(args)...) }-> Status;
};

versus

template <typename Fn, typename... Args>
concept has_request_interface = requires (Fn request, Args... args)
{
    { std::invoke(request, args...) }-> Status;
};

Is it meaningful using perfect forwarding in requires expressions ?

It seems to me that the answer is yes because the request callable object may expect rvalues for some arguments.

But does the requires (Fn request, Args... args) behave as a function declaration regarding the lvalue nature of args... ?

like image 763
JLM Avatar asked Jan 20 '20 18:01

JLM


People also ask

What is perfect forwarding?

What is Perfect Forwarding. Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.

What is a forwarding reference in C++?

When t is a forwarding reference (a function argument that is declared as an rvalue reference to a cv-unqualified function template parameter), this overload forwards the argument to another function with the value category it had when passed to the calling function.

Why is STD forward needed?

std::forward The need for this function stems from the fact that all named values (such as function parameters) always evaluate as lvalues (even those declared as rvalue references), and this poses difficulties in preserving potential move semantics on template functions that forward arguments to other functions.

How do you declare a concept in C++?

Let's define a few concepts in this post. A concept can be defined by a function template or by a variable template. A variable template is new with C++14 and declares a family of variables. If you use a function template for your concept, it's called a function concept; in the second case a variable concept.


1 Answers

It will behave exactly like what it looks like. That's kind of the point of a requires expression: to make these things look like C++. So it will behave like C++.

What matters is how you use the concept. That is, when you requires some template based on it, you should invoke the concept correctly. For example:

template<typename Func, typename ...Args
void constrained(Func func, Args &&...args)
  requires has_request_interface<Func, Args...>
{
  Status status = func(std::forward<Args>(args)...);
}

So yes, if you want forwarding through the concept to work, your concept needs to use && and forwarding.

like image 184
Nicol Bolas Avatar answered Sep 30 '22 17:09

Nicol Bolas