SFINAE — это технология, которая допускает недопустимые выражения и/или типы в непосредственном контексте шаблонной функции, в то время как concept
, по-видимому, имеет тот же эффект, поскольку нам разрешено использовать выражения и типы (в выражениях-требованиях) только в выражении-ограничении. определения концепции, а выражение-ограничения истинно, если все выражения и/или типы допустимы, и ложно в противном случае. Мне кажется, что concept
не может сделать ничего, кроме того, что может сделать SFINAE, то же самое верно и наоборот.
Правильно ли я понимаю? Если это не так, то в каком случае мы можем использовать только концепцию или использовать SFINAE, но использовать другой способ, что приведет к ошибке? Если такой сцены не существует, является ли концепция просто изящным/современным способом использования технологии SFINAE (т.е. они по существу эквивалентны)?
ИМО, единственная разница в том, что определенные выражения и типы, которые мы хотим проверить, рассредоточены в объявлении для SFINAE, в отличие от этого, определенные выражения и типы, которые мы хотим проверить, собраны в выражении ограничения единственного определения понятия и используют заявлено concept
в декларации. Их эффект по существу зависит от недопустимых выражений и типов.
SFINAE не делает включения.
SFINAE — это не столько технология, сколько взлом языка C++.
@chris Что здесь означает «подчинение»?
@ xmh0511, идея в том, что одна концепция представляет собой совокупность другой концепции плюс дополнительные требования, что влияет на перегрузку.
@bitmask Форма «понятия» такова. Недопустимые выражения и типы являются ядром SFINAE, в то время как недопустимые выражения и типы определяют результат концепции. Думаю, это просто трансформация формы.
@Крис Да. Однако недопустимые выражения и типы в концепции — это другие формы SFINAE, не так ли?
Концепты могут сделать одну важную вещь, которую не может сделать SFINAE, а именно быть удобочитаемыми для человека.
@н.м. Да, это единственная разница между ними, которую я упомянул в вопросе.
@JasonLiam Да, я не отрицал этого момента. Технически я думаю, что concept
и SFINAE
используют одну и ту же сущность (недопустимые выражения и типы). Если после подстановки возникают какие-либо недопустимые выражения и типы, для SFINAE объявление отбрасывается (SFINAE), а для концепта ограничение не выполняется, в общем случае объявление просто нежизнеспособно.
Да, концепции предназначены для того, чтобы превратить случайного хакера в первоклассного гражданина. Не случайно идеи пересекаются.
@StoryTeller-UnslanderMonica Итак, они по сути одинаковы, без каких-либо новых технологий. Они основаны на недопустимых выражениях и типах, просто одна концепция допускает несколько выражений и типов в своей коллекции, чтобы код выглядел элегантно, верно?
Нет, не совсем так. Вам уже сказали о подчинении. Это «новая технология». Не говоря уже о том, что уже с C++14 вы можете переносимо работать с несколькими вещами.
Они не эквивалентны. Понятия могут появляться в большем количестве мест и частично упорядочены по включению. Некоторые примеры:
1. Понятие включения может использоваться для ранжирования перегрузок. С SFINAE это ошибка:
template <typename T>
auto overload(T) -> std::enable_if_t<std::is_copy_constructible_v<T>>;
template <typename T>
auto overload(T) -> std::enable_if_t<std::is_move_constructible_v<T>>;
void test() {
overload(1); // error: ambiguous
}
С концепциями это работает:
void overload(std::copy_constructible auto);
void overload(std::move_constructible auto);
void test() {
overload(1);
}
2. Точно так же для ранжирования частичных специализаций можно использовать понятийное включение.
3. Концепции разрешены для функций-членов, не являющихся шаблонами, поэтому они могут ограничивать специальные функции-члены.
Поскольку конструктор копирования не является шаблоном, SFINAE никогда не применяется. Когда нужно условное поведение перед понятиями (например, тривиальный конструктор копирования, если аргумент шаблона шаблона класса сам по себе тривиален), нужно было условно ввести разные базовые классы.
4. Понятия могут ограничивать дедукцию.
Можно статически утверждать, что возвращаемый тип удовлетворяет вашим требованиям, не утверждая точный тип.
std::integral auto i = 1;
5. Концепции можно использовать в сокращенных шаблонах функций.
void f(std::integral auto);
Ах, концепты имеют отношения частичного порядка, определенные в [temp.constr.order], для которых SFINAE не может реализовать. Вы также перечисляете множество контекстов, в которых SFINAE нельзя использовать, спасибо.
concept
предназначены для (наряду с другими вещами) упрощения вашего кода.