I have a simple Vec3<T>
class, and I would like to update it using C++20 concepts (Clang 10.0.0 with -std=c++20). The new version looks something like this:
template <typename T> concept Arithmetic = std::is_arithmetic_v<T>;
template <typename T> concept FloatingPoint = std::is_floating_point_v<T>;
template <Arithmetic T> struct Vec3 {
T x, y, z;
/* operator overloading, etc.. */
void normalize() requires FloatingPoint<T>;
};
Is that a proper use of C++20 concepts? The core guideline T11 recommends using standard concepts as much as possible, but I couldn't find the ones I wanted in the list of C++ named requirements, nor in the <concepts>
header file. Is this because my concepts are too specific, and shouldn't be concepts at all in the first place?
My original code uses a mix of static_assert
and SFINAE to get to the end result.
C++20 Concepts - a Quick Introduction Concepts are a revolutionary approach for writing templates! They allow you to put constraints on template parameters that improve the readability of code, speed up compilation time, and give better error messages. Read on and learn how to use them in your code!
In short, a concept is a set of constraints on template parameters evaluated at compile time. You can use them for class templates and function templates to control function overloads and partial specialization. C++20 gives us language support (new keywords - requires, concept) and a set of predefined concepts from the Standard Library.
Additionally, the Standard Library is equipped with a set of predefined concepts (mainly obtained from existing type traits), making it easier to start. What’s more, C++20 offers even more language features to make the syntax even more compact.
You can use them for class templates and function templates to control function overloads and partial specialization. C++20 gives us language support (new keywords - requires, concept) and a set of predefined concepts from the Standard Library. In other words, you can restrict template parameters with a “natural” and easy syntax.
We already have a concept for a floating point type, it is std::floating_point
. The absence of std::arithmetic
seems to be an oversight and has already been noted, see N4844, page 50:
US 193. C++20 lacks a concept for arithmetic types. This omission is surprising, as this is a fairly common use case. For example, suppose I wish to write a function that squares a number. Pre C++20, I might write:
template <typename T> auto square(T x) {return x * x;}
In C++20, it would seem natural to be able to write:
auto square(std::arithmetic auto x) {return x * x;}
However, such a standard library concept is missing! Instead, we must write the more verbose:
template <typename T> requires std::is_arithmetic_v<T> auto square(T x) {return x * x;}
Proposed change:
template<class T> concept arithmetic = is_arithmetic_v<T>;
But the question of how std::arithmetic
should be defined is not that easy as it might seem to be. See this question. As Barry noted in the comment, that proposed change was rejected.
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