Is this a proper use of C++20 concepts?

Viewed 650

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.

1 Answers

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.

Related