2 분 소요

개요

  • 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> {}
  • 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;
        }