, .
. , , :
#include <string>
#include <locale>
using namespace std::literals;
// "EqualityComparable",
// T, , a b T,
// a==b , bool
template<typename T>
concept bool EqualityComparable = requires(T a, T b) {
{ a == b } -> bool;
};
void f(EqualityComparable&&); //
// template<typename T>
// void f(T&&) requires EqualityComparable<T>; //
int main() {
f("abc"s); // OK, std::string EqualityComparable
f(std::use_facet<std::ctype<char>>(std::locale{})); // : EqualityComparable
}
, , .
std::list<int> l = {3,-1,10};
std::sort(l.begin(), l.end());
// :
// invalid operands to binary expression ('std::_List_iterator<int>' and
// 'std::_List_iterator<int>')
// std::__lg(__last - __first) * 2);
// ~~~~~~ ^ ~~~~~~~
// ... 50 ...
//
// :
// error: cannot call std::sort with std::_List_iterator<int>
// note: concept RandomAccessIterator<std::_List_iterator<int>> was not satisfied
(Number, Range, RegularFunction), (HasPlus, Array). ISO C++ T.20, " , ."
, __cpp_concepts , 201507.
auto , - < --(optional)>, .
( ) ( )
std::pair<auto, auto> p2 = std::make_pair(0, 'a'); // auto int,
// auto char
Sortable x = f(y); // x f,
// , Sortable
auto f(Container) -> Sortable; //
// return,
// , Sortable
, (, )
void f(std::pair<auto, EqualityComparable>); // :
//
, auto, , -.
auto gl = [](Assignable& a, auto* b) { a = *b; };
, , :
template<size_t N> concept bool Even = (N%2 == 0);
struct S1 { int n; };
int Even::* p2 = &S1::n; // , ,
//
void f(std::array<auto, Even>); // , ,
//
template<Even N> void f(std::array<auto, N>); // OK
, , .
// :
void g1(const EqualityComparable*, Incrementable&);
// :
// template<EqualityComparable T, Incrementable U> void g1(const T*, U&);
// :
// template<typename T, typename U>
// void g1(const T*, U&) requires EqualityComparable<T> && Incrementable<U>;
void f2(std::vector<auto*>...);
// : template<typename... T> void f2(std::vector<T*>...);
void f4(auto (auto::*)(auto));
// : template<typename T, typename U, typename V> void f4(T (U::*)(V));
, , . (auto) .
void f0(Comparable a, Comparable* b);
// : template<Comparable T> void f0(T a, T* b);
void f1(auto a, auto* b);
// : template<typename T, typename U> f1(T a, U* b);
, , - { -()} , template : - , (, , ) .
, ( ), ( ) ( ) , .
EqualityComparable{T} class Foo;
// : template<EqualityComparable T> class Foo;
// : template<typename T> requires EqualityComparable<T> class Foo;
template<typename T, int N, typename... Xs> concept bool Example = ...;
Example{A, B, ...C} struct S1;
//
// template<class A, int B, class... C> requires Example<A,B,C...> struct S1;
:
Sortable{T} void f(T, auto);
// : template<Sortable T, typename U> void f(T, U);
// : void f(Sortable, auto);
| : , |
// ( )
template <class T, class U>
concept bool Derived = std::is_base_of<U, T>::value;
// ( )
template <class T>
concept bool EqualityComparable() {
return requires(T a, T b) { {a == b} -> Boolean; {a != b} -> Boolean; };
}
:
inlineconstexpr,inlineconstexprfriendvirtual- ,
noexcept(true). - ,
-
bool -
return, - ( , / -requires, )
:
-
bool - .
constexpr,constexpr- ( , / -requires, )
:
template<typename T>
concept bool F() { return F<typename T::type>(); } //
template<typename T>
concept bool V = V<T*>; //
, ( )
, . -requires ( )
9 :
-requires
template<typename T>
requires // -requires ( )
sizeof(T) > 1 && get_value<T>() //
void f(T);
, : , , , requires , , requires:
//
// Incrementable<T> && Decrementable<T>
template<Incrementable T> void f(T) requires Decrementable<T>;
template<typename T> requires Incrementable<T> && Decrementable<T> void f(T); // ok
// :
// Incrementable<T> && Decrementable<T>
// Decrementable<T> && Incrementable<T>
// .
// ,
template<Incrementable T> requires Decrementable<T> void g();
template<Decrementable T> requires Incrementable<T> void g(); //
P Q P && Q.
// ( )
template <class T>
concept bool Integral = std::is_integral<T>::value;
template <class T>
concept bool SignedIntegral = Integral<T> && std::is_signed<T>::value;
template <class T>
concept bool UnsignedIntegral = Integral<T> && !SignedIntegral<T>;
, . ( , : - ). operator&& .
P Q P || Q.
, . ( , ). operator|| .
// ( )
template <class T = void>
requires EqualityComparable<T>() || Same<T, void>
struct equal_to;
bool. , true
template<typename T> concept bool Size32 = sizeof(T) == 4;
, , .
bool, :
template<typename T> struct S {
constexpr explicit operator bool() const { return true; }
};
template<typename T>
requires S<T>{} // : S<T>{}
void f(T);
f(0); // :
requires :
template<typename T>
void f(T&&) requires Eq<T>; //
template<typename T> requires Addable<T> //
T add(T a, T b) { return a + b; }
bool, . true, , false :
template<typename T>
concept bool Addable = requires (T x) { x + x; }; // requires
template<typename T> requires Addable<T> // requires, requires
T add(T a, T b) { return a + b; }
template<typename T>
requires requires (T x) { x + x; } // , ,
//
T add(T a, T b) { return a + b; }
requires :
requires ( -() ) { - }
|
|||||||||
| - | , , , , , . , . } -. ,
| |
| - | , ( ). , requires. |
- :
, , , -. , -requires, ,
-requires . ,
template<class T> concept bool C = requires {
new int[-(int)sizeof(T)]; // T: ,
//
};
. , ( ). , , .
template<typename T>
concept bool Addable =
requires (T a, T b) {
a + b; // " a+b , "
};
// ( )
template <class T, class U = T>
concept bool Swappable = requires(T&& t, U&& u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t));
};
typename , . , ( ): , , , .
template<typename T> using Ref = T&;
template<typename T> concept bool C =
requires {
typename T::inner; //
typename S<T>; //
typename Ref<T>; //
};
// ( )
template <class T, class U> using CommonType = std::common_type_t<T, U>;
template <class T, class U> concept bool Common =
requires (T t, U u) {
typename CommonType<T, U>; // CommonType<T, U>
{ CommonType<T, U>{std::forward<T>(t)} };
{ CommonType<T, U>{std::forward<U>(u)} };
};
{ } noexcept() --() ;
|
|||||||||
:
noexcept, noexcept ( )template<typename T> concept bool C2 =
requires(T x) {
{*x} -> typename T::inner; // *x
// T::inner
// *x T::inner
};
// ( )
template <class T, class U> concept bool Same = std::is_same<T,U>::value;
template <class B> concept bool Boolean =
requires(B b1, B b2) {
{ bool(b1) }; //
{ !b1 } -> bool; //
requires Same<decltype(b1 && b2), bool>; // ,
requires Same<decltype(b1 || b2), bool>;
};
-requires, . ( ), , ( requires, requires, , , )
//
template <class T>
concept bool Semiregular = DefaultConstructible<T> &&
CopyConstructible<T> && Destructible<T> && CopyAssignable<T> &&
requires(T a, size_t n) {
requires Same<T*, decltype(&a)>; // : "Same<...> true"
{ a.~T() } noexcept; // : "a.~T()" ,
//
requires Same<T*, decltype(new T)>; // : "Same<...> true"
requires Same<T*, decltype(new T[n])>; //
{ delete new T }; //
{ delete new T[n] }; //
};
, ( ) : , -.
, - ( )
void f(Concept); std::vector<Concept> x = ...;template<Concept T> void f();Concept{T} struct X;template<typename T> void f() requires Concept<T>;template<typename T> concept bool C() { return true; } // #1
template<typename T, typename U> concept bool C() { return true; } // #2
void f(C); // , C, #1 #2;
// ( ) #1.
, , ( , ), , . (, , ). -,
template<typename T> concept bool C1() { return true; } // #1
template<typename T, typename U> concept bool C1() { return true; } // #2
void f1(const C1*); // < > <T>, #1
template<typename T> concept bool C1() { return true; } // #1
template<typename T, typename U> concept bool C1() { return true; } // #2
void f2(C1<char>); // < , char> <T, U>, #2
template<typename... Ts>
concept bool C3 = true;
C3{T} void q2(); // OK: <T> <...Ts>
C3{...Ts} void q1(); // OK: <...Ts> <...Ts>
template<typename T> concept bool C() { return true; } // #1
template<typename T, typename U> concept bool C() { return true; } // #2
template <typename T>
void f(T) requires C<T>(); // #1
. ( ) , , . , (, , ), . , ( ).
- , , , . , .
template<typename T> concept bool C2() { return true; }
template<int T> concept bool C2() { return true; }
template<C2<0> T> struct S1; // : < , 0>
// <typename T> <int T>
template<C2 T> struct S2; // #1 #2:
| : , 'return true' |
requires , , , , , , .
, P , Q , :
-
AA -
AA||BA&&B -
A&&BA,A||BA
, :
| : |
D1 D2 , D1 D2 ( D1 , D2 ), , D1 , D2. D1 , D2, D2 , D1, D1 , D2.
template<typename T>
concept bool Decrementable = requires(T t) { --t; };
template<typename T>
concept bool RevIterator = Decrementable<T> && requires(T t) { *t; };
// RevIterator Decrementable,
// RevIterator , Decrementable
void f(Decrementable); // #1
void f(RevIterator); // #2
f(0); // int Decrementable, #1
f((int*)0); // int* , #2
void g(auto); // #3 ()
void g(Decrementable); // #4
g(true); // bool Decrementable, #3
g(0); // int Decrementable, #4,
GCC >= 6.1 ( -fconcepts)