Во вложенном требовании зачем использовать `требуется bool_constant::value;` вместо `требуется X;`?

#c #c 20

#c #c 20

Вопрос:

Я читал эту страницу cppreference и нашел в ней следующий код:

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

Мне любопытно, почему std::bool_constant здесь используется. Разве это невозможно использовать requires G::min() < G::max(); напрямую, вот так:

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

Ответ №1:

Потому что requires G::min() < G::max(); это серьезная ошибка, если G::min() < G::max() не формирует постоянное выражение, а requires std::bool_constant<(G::min() < G::max())>::value просто было бы false .

Возьмем, к примеру, этот тип и эти понятия:

 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>); выполняется, как и ожидалось, поскольку формирует недопустимое выражение, поэтому оно равно false.

static_assert(!min_max_1<foo>); создает ошибку времени компиляции, потому что T::min() < T::max() это допустимое выражение, это просто не постоянное выражение bool, чего и следовало ожидать.