Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concept with multiple template arguments

I'm trying to use C++20 concepts, to start familiarizing with them. I feel pretty comfortable with easy concepts, for example with the standard concept movable I can write something like this (in all examples I suppose I'm using namespace std and I included <concepts> and any other header needed):

template<movable T>
int foo (T obj);

And be sure that when this function is called the passed object obj can be moved. I can write this even in a longer form:

template<typename T>
requires movable<T>
int foo (T obj);

And the result would be the same (I think).

But now let's look at another concept such as same_as. same_as takes 2 templates parameter (the 2 types to compare), so I can write:

template<typename T>
requires same_as<T, string>
int bar (T obj);

And now T is string. But How can I write it in the shorter form? I tried, and I can write this (as I intuitively expected):

template<same_as<string> T>
int bar (T obj);

But what is the formal rule behind this form?

Is the name (T) of the function template parameter, entered as first argument of the concept template? Or maybe as last? I don't know, there is very little information about this topic. I mean, in this example it is irrelevant, because same_as<A, B> is semantically equivalent to same_as<B, A>, but there are for sure cases where the order matters.


I know there are questions with similiar titles, such as this one, but it asks a different thing.

These are the resources I tried to get information from, but failed: cppReference, cppModernes, open-std (I browsed years 2018, 2019 and 2020) and this post.

like image 513
Lapo Avatar asked Apr 26 '20 16:04

Lapo


People also ask

Which template can have multiple parameters?

C++ Templates: Templates with Multiple Parameters | C++ Tutorials for Beginners #65.

How can we use more than one argument with a function template?

When argument is more than one, they are separated by commas. Test test1 (1.23, 123); tells the compiler that the first argument is of type float and another one is int type. During creation of objects, constructor is called and values are received by template arguments.

What is a template argument?

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.

What is function templates C++ with multiple parameters with suitable example?

Function Templates with Multiple Parameters You can also use multiple parameters in your function template. The above syntax will accept any number of arguments of different types. Above, we used two generic types such as A and B in the template function.


1 Answers

But what is the formal rule behind this form?

The rule (that you correctly guessed your way into) is described in [temp.param]/4:

A type-constraint Q that designates a concept C can be used to constrain a contextually-determined type or template type parameter pack T with a constraint-expression E defined as follows. If Q is of the form C<A1, ⋯, An>, then let E′ be C<T, A1, ⋯, An>. Otherwise, let E′ be C<T>. If T is not a pack, then E is E′, otherwise E is (E′ && ...). This constraint-expression E is called the immediately-declared constraint of Q for T. The concept designated by a type-constraint shall be a type concept ([temp.concept]).

With examples in the subsequent paragraph:

A type-parameter that starts with a type-constraint introduces the immediately-declared constraint of the type-constraint for the parameter. [ Example:

template<typename T> concept C1 = true;
template<typename... Ts> concept C2 = true;
template<typename T, typename U> concept C3 = true;

template<C1 T> struct s1;               // associates C1<T>
template<C1... T> struct s2;            // associates (C1<T> && ...)
template<C2... T> struct s3;            // associates (C2<T> && ...)
template<C3<int> T> struct s4;          // associates C3<T, int>
template<C3<int>... T> struct s5;       // associates (C3<T, int> && ...)

— end example ]

You can also think of template <C T> as being shorthand for template <C<> T>, and then the type parameter T just always slots into the first argument of the concept.

like image 79
Barry Avatar answered Sep 28 '22 16:09

Barry