std::concepts
개요
C++ Concepts는 템플릿 파라미터에 대한 제약 조건을 명시적으로 표현하는 기능입니다. 템플릿이 특정 요구사항(예: 특정 멤버 함수나 연산자를 지원)을 만족하는 타입에 대해서만 인스턴스화되도록 강제할 수 있습니다. 이를 통해 컴파일 타임에 타입 요구사항을 검증하고, 의도에 맞지 않는 타입이 사용될 경우 훨씬 명확하고 이해하기 쉬운 에러 메시지를 생성할 수 있습니다.
C++ 버전별 주요 키워드 도입 시기
- C++20:
concept
,requires
키워드가 도입되어 Concepts 기능이 표준으로 채택되었습니다.
내용 설명
Concepts는 concept
키워드를 사용하여 정의하며, requires
절을 통해 템플릿 파라미터가 만족해야 할 제약 조건을 기술합니다. 여러 Concepts를 논리 연산자(&&
, ||
, !
)로 조합하여 더 복잡한 제약 조건을 만들 수도 있습니다.
제공된 예제 코드는 세 가지 concept
를 정의하고 활용합니다.
Addable
:+
연산자를 사용하여 같은 타입의 두 객체를 더할 수 있는지 검사합니다.NonNumeric
:std::integral
과std::floating_point
타입 특성(type traits)을 사용하여 해당 타입이 정수나 부동소수점 숫자가 아닌지 검사합니다.Concatenable
:Addable
과NonNumeric
두concept
를&&
연산자로 조합하여,+
연산이 가능하면서도 숫자 타입이 아닌 경우로 제약 조건을 정의합니다. 즉, '연결' 가능한 타입을 의도합니다.
concat
함수는 Concatenable
concept
를 만족하는 타입 T
에 대해서만 인스턴스화됩니다. 따라서 std::string
과 같이 +
연산자로 문자열 연결이 가능하고 숫자 타입이 아닌 경우에만 concat
함수를 사용할 수 있습니다.
예제 코드
#include <concepts>
#include <iostream>
#include <string>
template <typename T>
concept Addable = requires(T x)
{
x + x;
};
template <typename T>
concept NonNumeric = !std::integral<T> && !std::floating_point<T>;
template <typename T>
concept Concatenable = Addable<T> && NonNumeric<T>;
template <typename T>
requires Concatenable<T> T concat(T first, T second)
{
return first + second;
}
int main()
{
const auto s1 = std::string{"Hel"};
const auto s2 = std::string{"lo"};
std::cout << concat(s1, s2) << std::endl;
// std::cout << concat(1, 2) << std::endl; // 컴파일 에러 발생
return 0;
}
실행 결과
Hello
concat(s1, s2)
:std::string
은+
연산이 가능하고(Addable
만족) 숫자 타입이 아니므로(NonNumeric
만족),Concatenable
제약 조건을 통과하여 정상적으로 "Hello"를 출력합니다.concat(1, 2)
:int
타입은+
연산이 가능하지만(Addable
만족),std::integral<int>
가true
이므로NonNumeric
제약 조건을 만족하지 못합니다. 따라서Concatenable
제약 조건에 위배되어 컴파일 에러가 발생합니다. Concepts 덕분에 에러 메시지가 "템플릿 인스턴스화 실패"와 같은 복잡한 내용 대신 "제약 조건 불일치"로 명확하게 표시됩니다.
활용팁
- 가독성 향상: 템플릿 인터페이스가 어떤 타입을 요구하는지 코드만으로 명확하게 알 수 있습니다.
- 컴파일 에러 개선: SFINAE(Substitution Failure Is Not An Error)와 비교하여 훨씬 직관적이고 이해하기 쉬운 컴파일 에러 메시지를 제공합니다.
- 오버로딩:
concept
를 사용하여 특정 타입 그룹에 대한 함수 오버로딩을 더 쉽게 구현할 수 있습니다. - 표준 라이브러리 활용: C++20 표준 라이브러리의 많은 부분(예: Ranges)이 Concepts를 기반으로 재설계되어 더욱 안전하고 효율적인 코드를 작성할 수 있습니다.
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : Type Traits 1 (11, 14, 17, 20) (0) | 2025.09.24 |
---|---|
Modern C++ : 템플릿 특수화 (Template Specialization) (98, 11, 17) (0) | 2025.09.23 |
Modern C++ : 복사 및 이동 의미론 (Copy and Move Semantics) (98, 11) (0) | 2025.09.22 |
Modern C++ : 연산자 오버로딩 (Operator Overloading) (98, 11, 20) (0) | 2025.09.21 |
Modern C++ : 클래스 템플릿(Class Template) (98) (0) | 2025.09.20 |
Modern C++ : 다형성(Polymorphism) (98, 11) (0) | 2025.09.19 |
Modern C++ : 상속(Inheritance) (98, 11) (0) | 2025.09.18 |
Modern C++ : 클래스(Class) (98, 11, 17) (0) | 2025.09.17 |