Is concept a variant of SFINAE
Problem Description:
SFINAE is a technology that permits invalid expressions and/or types in the immediate context of a templated function while the concept
seems to have the same effect since we are only permitted to use expressions and types(in requires-expression) in the constraint-expression of the concept-definition, and the constraint-expression is true if all expressions and/or types are valid, and false otherwise. It appears to me that concept
cannot do anything that exceeds what SFINAE can do, the same is true the other way around.
Is my understanding right? If it is not, what is the case in which we can only by using the concept, or by using SFINAE but using the other way would result in an error? If there does not exist such a scene, is the concept merely a graceful/modern way of using the technology SFINAE(i.e. they are essentially equivalent)?
Update:
IMO, the only difference is, certain expressions and types we want to check are dispersed in the declaration for SFINAE, by contrast, certain expressions and types we want to check are collected in the constraint-expression of the single concept-definition and use the declared concept
in the declaration. Their effect essentially relies on invalid expressions and types.
Solution – 1
They are not equivalent. Concepts can appear in more places and are partially ordered by subsumption. Some examples:
1. Concept subsumption may be used to rank overloads. With SFINAE, this is an error:
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
}
With concepts, this works:
void overload(std::copy_constructible auto);
void overload(std::move_constructible auto);
void test() {
overload(1);
}
2. Similarly, concept subsumption may be used to rank partial specializations.
3. Concepts are allowed on non-template member functions, so they can constrain special member functions.
Since a copy constructor is not a template, SFINAE never applies. When one needs conditional behavior before concepts (e.g. trivial copy constructor if the template argument of the class template is itself trivial), one had to conditionally introduce different base classes.
4. Concepts can constrain deduction.
One can statically assert that a type returned satisfies your requirements without asserting the precise type.
std::integral auto i = 1;
5. Concepts can be used in abbreviated function templates.
void f(std::integral auto);