반응형
우리가 C#에서 제네릭 문법을 사용할 때 위와 같은 코드로 추가적인 조건을 붙여줄 수 있었다.
기존 C++에는 비슷하게 나마 사용하려면 enable_if를 사용하여 복잡하게 코드를 작성해야 했었다.
하지만 C++ 20 부터는 새로운 개념이 생겼다.
바로 Concept 이다. 이를 이용하여 템플릿 매개변수에 제약을 걸 수 있게 된다.
사용방법에는 4가지가 있다.
예제로 정수 타입만 받아서 출력하는 함수 코드를 작성해보았다.
1) Requires Clause
template<typename T>
requires std::integral<T>
void TestConcept(T number)
{
cout << number << endl;
}
2) Trailing Requires Clause (뒤에 붙는~)
template<typename T>
void TestConcept2(T number) requires std::floating_point<T>
{
cout << number << endl;
}
3) Constrained Template Parameter (강요된)
template<std::integral T>
void TestConcept3(T number)
{
cout << number << endl;
}
4) Abbreviated Function Template
void TestConcept4(std::integral auto number)
{
cout << number << endl;
}
이런 식으로 제약을 건 조건에 부합하는 매개변수만 오류가 발생하지 않는다.
이를 이용해서 맨처음 C#으로 작성된 코드를 C++로 작성해보면 아래와 같다.
그리고 Concept은 내가 필요한 조건으로 만들어 줄 수도 있다.
template<typename T> //정수가 아니고 GameObject를 상속받았어야 함.
concept MyConcept = !std::is_integral_v<T> && std::derived_from<T, GameObject>;
template<typename T> //a+b가 가능해야 함.
concept Addable = requires(T a, T b)
{
a + b;
};
template<typename T> //비교를 할 수 있어야함. (== 또는 !=)
concept Equality = requires(T a, T b)
{
{a == b} -> std::convertible_to<bool>;
{a != b} -> std::convertible_to<bool>;
};
template<typename T>
concept Integral = std::is_integral_v<T>;
template<typename T>
concept SignedInt = Integral<T> && std::is_signed_v<T>;
미리 정의된 Concept
이름 | 설명 |
std::three_way_comparable<T, U> | <=>연산자 a <=> b 일때 a가 작으면 -1, 같으면 0, a가 크면 1을 리턴합니다. 다음의 조건을 만족하는지 체크합니다. 1. (a <=> b == 0) == bool(a == b)가 true 2. (a <=> b != 0) == bool(a != b)가 true 3. ( (a <=> b) <=> 0) 와 ( 0 <=> (a <=> b) )가 상등(equal) 4. (a <=> b < 0) == bool(a < b)가 true 5. (a <=> b > 0) == bool(a > b)가 true 6. (a <=> b <= 0) == bool(a <= b)가 true 7. (a <=> b >= 0) == bool(a >= b)가 true |
std::same_as<T, U> | 두 형식이 같은지 체크 |
std::derived_from<T, U> | template<class _Derived, class _Base> 형식의 콘셉트 첫번째 인자가 두번째 인자의 파생 형식인지 체크 |
std::convertible_to<T, U> | template <class _From, class _To> 형식의 콘셉트 첫번째 인자가 두번째 인자로 변환이 가능하지 체크 std::convertible_to<char* , std::string> : true std::convertible_to<std::string, char*> : false |
std::common_reference_with<T, U> | 두 형식을 어떤 공통의 참조 형식으로 변환 할 수 있음 std::common_reference_with<T, U>일 때 T, U가 어떤 형식 참조형식인 C로 변환 가능 체크 |
std::common_with<T, U> | std::common_reference_with 비슷한데 참조형식이 아니고 값 형식이여도 가능 |
std::assignable_from<T, U> | std::assignable_from<_LTy, _RTy> _LTy이 참조 형식이어야 하고 _RTy을 _LTy으로 배정 할 수 있어야 합니다. |
std::swappable<T, U> | 두 형식의 값을 교환 할 수 있음 |
std::integral<T> | 정수 형식(char, short, int, long, unsigned 형식) |
std::signed_integral<T> | 부호 있는 정수 형식(char, short, int, long,) |
std::unsigned_integral<T> | 부호 없는 정수 형식(unsigned + char, short, int, long,) |
std::floating_point<T> | 부동 소수점 형식(float, double, long double) |
std::destructible<T> | 소멸자 사용 가능 여부 |
std::constructible_from<T, ...Args> | std::constructible_from<_Ty, ... _ArgTys> 형식으로 _Ty 객체를 생성할 수 있는지 체크 |
std::default_initializable<T> | 객체 기본 생성자 호출 가능 여부 |
std::move_constructible<T> | 객체 이동 생성자 호출 가능 여부 |
std::copy_constructible<T> | 객체 복사 생성자 호출 가능 여부 |
std::equality_comparable<T> | 객체 상등 비교 가능 여부 |
std::totally_ordered<T> | 전 순서 집합 가능 여부 |
std::moveable<T> | 이동 가능 여부 is_object_v && move_constructible && assignable_from<T&, T> && swappable |
std::copyable<T> | 복사 가능 여부 copy_constructible && movable && assignable_from<T&, T&>, <T&, const T> <T&, const T&> |
std::semiregular<T> | 준 정규 형식 여부 copyable && default_initializable |
std::regular<T> | 정규 형식 여부 semiregular && equality_comparable |
std::invocable<F, ...Args> | std::invoke를 호출 할 수 있는지 여부 |
std::regular_invocable<F, ...Args> | invocable에 상등을 보존하고 함수 인수들을 수정하지 않습니다. |
std::predicate<F, T, U> | invocable하며 bool 값을 돌려 줍니다. |
std::input_iterator<It> | 입력 반복자 |
std::output_iterator<It, T> | 출력 반복자 |
std::forward_iterator<It> | 순방향(전진) 반복자 |
std::bidirectional_iterator<It> | 양방향 반복자 |
std::random_access_iterator<It> | 임의 접근 반복자 |
std::contiguous_iterator<It> | 연속 반복자 연속 반복자를 지원하려면 컨테이너 요소들을 메모리에 연속해서 저장 해야 합니다. (std::array, std::vector, std::string) |
std::permutable<It> | 요소들이 제자리 순서 변경이 가능함 std::forward_iterator |
std::mergeable<It1, It2, Out> | 정렬된 순차열들을 병합해서 출력 순차열로 산출 할 수 있음 |
std::sortable<It> | 요소들의 순서를 변경해서 정렬된 순차열을 만들 수 있음 |
반응형
'C++' 카테고리의 다른 글
C++ 20 : Range(중요) (0) | 2024.05.15 |
---|---|
C++ 20 : Module(중요) (0) | 2024.05.14 |
C++ 20 (0) | 2024.05.14 |
lvalue, rvalue (0) | 2024.01.05 |
c++ 람다 (0) | 2023.02.07 |