требует ограничения должны оценить, чтобы bool.так что не СФИНАЕ - PullRequest
0 голосов
/ 27 ноября 2018

Мне любопытно, что в главе «Атомные ограничения» https://en.cppreference.com/w/cpp/language/constraints

написано

Тип E после замены должен быть точно bool.Преобразование не допускается

и

f(0); // error: S<int>{} does not have type bool when checking #1,
          // even though #2 is a better match

ой.что означает, что нет механизма SFINAE при работе с пунктами require?Разве это не облом ?
Потому что я вижу, как некоторые типы шаблонов могут привести к bool после прохождения выражения, но не другие.И теперь мы вернулись, чтобы использовать enable_if и прочее.сильно болит?

1 Ответ

0 голосов
/ 27 ноября 2018

Цель этого ограничения состоит в том, чтобы усложнить ошибку, приводящую к неудовлетворительным или всегда удовлетворяемым понятиям, например:

template<class T> concept C1 = sizeof(T); // Oops, I meant to write sizeof(T) >= 2

Если sizeof(T) неявно преобразовать в boolC будет удовлетворено всеми законченными типами объектов.На практике вы можете просто принудительно преобразовать выражение в bool, если вы действительно этого хотите:

template<class T> concept C2 = (bool)sizeof(T); // I did *not* mean to write sizeof(T) >= 2

Обратите внимание, что концепции не удовлетворяются, когда подстановка создает недопустимое выражение (https://godbolt.org/z/xMHoJ0):

template<class T> concept C3 = (bool)T::value;
static_assert(C3<std::true_type>);
static_assert(!C3<int>);

или тип (https://godbolt.org/z/tnreG0):

template<class T> concept C4 = C3<typename T::type>;
static_assert(C4<std::is_same<int, int>>);
static_assert(!C4<int>);

, так что «требующие-пункты не делают SFINAE!» Точно не характеризует ситуацию.

Полагаю, я должен указатьИз других возможных ошибок - атомные выражения ограничений должны быть константными выражениями. Если подстановка в выражение ограничения создает неконстантное выражение, программа некорректна (https://godbolt.org/z/LQA1XQ):

template<class T> concept C5 = T::f();

struct S1 {
    static constexpr bool f() { return true; }
};

struct S2 {
    static constexpr bool f() { return false; }
};

struct S3 {
    static bool f() { return true; }
};

static_assert(!C5<void>); // Invalid expression: SFINAE and concept is not satisfied
static_assert(!C5<int>);  // Ditto

static_assert(C5<S1>);  // Constant expression that evaluates to true
static_assert(!C5<S2>); // Constant expression that evaluates to false

static_assert(C5<S3>);  // Ill-formed: not a constant expression
...