[C++] concepts
Updated:
개요
- Named sets of such requirements
- 이름을 가진 요구사항의 집합
- 타입이 가져야 하는 요구사항을 정의하는 문법
- 제약 조건을 지정
- 템플릿 인자
- 변수 선언
- 제약 조건은 컴파일 타임에 평가
- 함수 오버로딩이나 템플릿 특수화에서 가장 적절한 함수를 선택하는데 사용
- 기존에는 템플릿 인자의 타입에만 의존하여 함수 오버로딩 가능
- concept은 타입뿐만 아니라 속성 혹은 연산자에 따라 함수 오버로딩 가능
- 런타임에 수행하던 논리 연산들이 컴파일 타임에 결정되어 에러 검출 시점 앞당김 및 실행 속도 향상
- 컴파일 에러 가동성 증가
concept
- 문법
- 정의
template < template-parameter-list > concept concept-name = constraint-expression;
- 사용
- requires clause
- 템플릿 선언 뒤에 requires 선언
template <typename T> requires over4<T>
- constrained type template parameter
- 템플릿 인자에 선언
- template
auto func(T t) {}
- abbreviated function template declaration
- 파라미터에 선언
auto func(over4 auto t) {}
- trailing requires clause
- 함수 선언 뒤에 requires 선언
template <typename T> auto func(T t) requires over4<T> {}
- requires clause
- concepts library
- 정의
- 예제
- 코드
#include <concepts> #include <iostream> #include <string> #include <type_traits> using namespace std; template <typename T> concept over4 = sizeof(T) >= 4; template <typename T> requires over4<T> auto howToUseConcept_1(T t) { cout << "over4" << endl; } template <typename T> auto howToUseConcept_1(T t) { cout << "not over4" << endl; } template <over4 T> auto howToUseConcept_2(T t) {} auto howToUseConcept_3(over4 auto t) {} template <typename T> auto howToUseConcept_4(T t) requires over4<T> {} template <class T> concept integeral = is_integral<T>::value; int main() { howToUseConcept_1(int()); howToUseConcept_1(short()); cout << integral<int> << endl; cout << integral<string> << endl; auto i1 = int(1); over4 auto i2 = int(2); // over4 i3 = short(); cout << i1 << endl; cout << i2 << endl; return 0; }
- 실행 결과
over4 not over4 1 0 1 2
- 코드
requires clauses
- 문법
template<typename T> void f(T&&) requires Eq<T>;
- requires 뒤에는 상수 표현식이여야함
- 예제
- 코드
#include <concepts> using namespace std; template <typename T> concept over4 = sizeof(T) >= 4; template <typename T> requires over4<T> void func(T t) {} template <typename T> requires(sizeof(T) >= 4) void func(T t) {} template <typename T> requires true void func(T t) {} template <typename T> requires false void func(T t) {} template <typename T> requires is_pointer<T>::value void func(T t) {} constexpr bool check() { return true; } template <typename T> requires(check()) void func(T t) {} template <typename T> requires is_pointer<T>::value &&(check()) void func(T t) {} int main() { return 0; }
- 코드
requires expression
- 문법
requires { requirement-seq } requires ( parameter-list(optional) ) { requirement-seq }
- 예제
- 코드
#include <concepts> #include <iterator> #include <vector> using namespace std; template <typename T> concept concept_1 = requires { typename T::iterator; }; template <concept_1 T> void func1(T t) {} template <typename T> concept concept_2 = requires(T t) { t.size(); }; template <concept_2 T> void func2(T t) {} template <typename T> concept concept_3 = requires(T t) { t.size(); t.begin(); t.end(); }; template <concept_3 T> void func3(T t) {} template <typename T> concept concept_4 = requires(T t1, T t2) { t1 < t2; t1 == t2; t1 > t2; }; template <concept_4 T> void func4(T t1, T t2) {} template <typename T1, typename T2> concept concept_5 = requires(T1 t1, T2 t2) { t1.size(); t2.begin(); t2.end(); }; template <typename T1, typename T2> requires concept_5<T1, T2> void func5(T1 t1, T2 t2) {} class Test { public: int size() { return 0; } }; int main() { // func1(int()); func1(vector<int>{}); // func2(int()); func2(Test()); func2(vector<int>{}); // func3(Test()); func3(vector<int>{}); func4(1, 2); func4("a", "b"); // func4(1, "1"); func5(Test(), vector<int>{}); // func5(vector<int>{}, Test()); return 0; }
- 코드