I'm trying to wrap my head around concepts in C++20. Consider the following (very simple) concept:
template <typename T>
concept Float = requires
{
std::floating_point<T>;
};
I can write a templated class using this concept in 2 ways:
template <Float T>
class MyClass {
public:
MyClass(T val) : value{ val } {};
private:
T value;
};
Or I can do
template <typename T> requires Float<T>
class MyClass {
public:
MyClass(T val) : value{ val } {};
private:
T value;
};
In this particular example, these behave exactly the same. Is this always the case though? Are there situations where it is easier to express some constraint using the template <...> requires ... syntax? Or is this merely a style preference/convention?
The only thing I can think of right now is that using the template <...> requires ... syntax may allow you represent relational constraints between multiple template arguments, where as the template <CONCEPT T> syntax only allows you to represent a constraint on a single argument?
Any guidance would be much appreciated.
There is no difference between:
template <Float T>
and
template <typename T> requires Float<T>
They mean the same thing. If you declare a template and then define it later, you have to use the same syntax in both places - but both syntaxes do mean the same thing.
It's purely a matter of preference. The type-constraint syntax is more limited (can only be used to constrain a type) but can be more readable.
Note that the type-constraint syntax can express multi-type constraints. For instance the typical ranges pattern of:
template <typename I, typename S>
requires input_iterator<I>
and sentinel_for<S, I>
void algo(I, S);
can be written with the shorthand:
template <input_iterator I, sentinel_for<I> S>
void algo(I, S);
Using concept names in place of typenames is always a shorthand for something you could do in long-form. However, there are some circumstances where the long-form equivalent is more unwieldy.
For example:
template <Concept auto value>
class foo {...};
//becomes
template <auto value> requires Concept<decltype(value)>
class foo {...};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With