실행 중인 C++ 개념

2764 단어 templatescppcpp20
C++20에는 개발자가 템플릿 매개변수에 제약 조건을 지정할 수 있는 Concept이라는 새로운 기능이 있습니다. 템플릿 메타 프로그래밍은 노련한 베테랑도 당황하게 만드는 복잡한 주제입니다. 범위 기반 반복(기본적으로 시작 및 종료 메서드가 있는 유형)을 지원하는 C++ 컨테이너를 출력할 수 있는 오버로드된 스트림 삽입 연산자를 작성할 수 있도록 이 기능의 흥미로운 사용법을 발견했습니다.

#include <iostream>
#include <unordered_map>
#include <array>
#include <vector>
using namespace std;

template<typename ContainerType>
concept SupportsRangeBasedFor = requires(ContainerType container) {
    container.begin();
    container.end();
};

template<typename KeyType, typename ValueType>
ostream& operator<<(ostream& os, const pair<KeyType, ValueType>& p) {
    os << p.first << "->" << p.second;
    return os;
}

ostream& operator<<(ostream& os, SupportsRangeBasedFor auto&& container) {
    os << "[ ";
    for (const auto& element : container) {
        os << element << ' ';
    }
    os << ']' << endl;
    return os;
}

int main()
{
    cout << vector<int>{1,2,3} << endl;
    cout << array<int,3>{4,5,6} << endl;
    cout << unordered_map<int,int>{{8,9},{10,11},{11,12}} << endl;
    //struct Foo {};
    //cout << Foo {} << endl; // Compiler Error: No overload for operator<< that accepts Foo
    return 0;
}


이 프로그램을 실행하면 다음과 같은 출력이 생성됩니다.

~/code/cpp/concepts > ./concept
[ 1 2 3 ]

[ 4 5 6 ]

[ 11->12 10->11 8->9 ]



따라서 시작 및 종료 메서드가 있는 모든 컨테이너를 지원할 수 있는 단일 오버로드가 있습니다. 이것은 마법이 아닙니다. SupportsRangeBasedFor 개념 없이 작동하도록 할 수 있었지만 마법은 개념이 발생하지 않도록 방지하는 것입니다.

템플릿 매개 변수에 대한 제약 조건이 없으면 컴파일러는 operator<<에 대해 Foo 오버로드를 선택했을 것이며 Foobeginend 메서드가 없다는 사실로 인해 해독할 수 없는 오류 덩어리가 발생합니다. . 다음과 같은 성격의 오류가 표시됩니다.

concept.cpp:22:30: error: invalid range expression of type 'Foo'; no viable 'begin' function available
    for (const auto& element : container) {
                             ^ ~~~~~~~~~
concept.cpp:35:10: note: in instantiation of function template specialization 'operator<<<Foo>' requested here
    cout << Foo {} << endl; 


뿐만 아니라 템플릿 매개 변수 유형(ostream.operator<<(...) 유형 지정자로 도입됨)이 모든 유형과 일치하기 때문에 컴파일러는 이 오버로드에 대한 모든 auto 호출을 일치시킵니다.

개념으로 표현된 유형 제약 조건은 컴파일러가 지원하지 않으려는 유형에 대한 템플릿 함수를 선택하는 것을 명시적으로 금지합니다. 이것은 꽤 깔끔한 기능이며 향후 개발에서 구현을 선택해야 하는 유형을 제한하기 위해 이것을 상당히 광범위하게 사용하기를 바랍니다. :)

좋은 웹페이지 즐겨찾기