개요
- 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
template <typename T> auto func(T t) requires over4<T> {}
- 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;
}
- 실행 결과
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;
}