Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a nested requirement, why use `requires bool_constant<X>::value;` instead of `requires X;`?

Tags:

c++

c++20

I was reading this cppreference page, and found following code in it:

template <class G>
concept uniform_random_bit_generator =
  // ...
  requires {
    // ...
    requires std::bool_constant<(G::min() < G::max())>::value;
  };

I'm curious why std::bool_constant is used here. Isn't it possible to use requires G::min() < G::max(); directly, like so:

template <class G>
concept uniform_random_bit_generator =
  // ...
  requires {
    // ...
    requires G::min() < G::max();
  };
like image 448
HolyBlackCat Avatar asked Aug 23 '20 14:08

HolyBlackCat


1 Answers

Because requires G::min() < G::max(); is a hard error if G::min() < G::max() doesn't form a constant expression, but requires std::bool_constant<(G::min() < G::max())>::value would just be false.

Take for example this type and these concepts:

struct foo {
    static int min();
    static int max();
};

template<typename T>
concept min_max_1 = requires {
    requires T::min() < T::max();
};

template<typename T>
concept min_max_2 = requires {
    requires std::bool_constant<(T::min() < T::max())>::value;
};

// Which are entirely equivalent to
template<typename T>
concept min_max_1 = T::min() < T::max();

template<typename T>
concept min_max_2 = std::bool_constant<(T::min() < T::max())>::value;

static_assert(!min_max_2<foo>); succeeds as expected, because it forms an invalid expression so it is false.

static_assert(!min_max_1<foo>); creates a compile time error, because T::min() < T::max() is a valid expression, it's just not a bool constant expression, which is what is expected.

like image 161
Artyer Avatar answered Oct 18 '22 22:10

Artyer