C++/STL

[C++20] Concepts

sseram 2023. 5. 23. 21:49
반응형

https://en.cppreference.com/w/cpp/concepts

 

Concepts library (since C++20) - cppreference.com

The concepts library provides definitions of fundamental library concepts that can be used to perform compile-time validation of template arguments and perform function dispatch based on properties of types. These concepts provide a foundation for equation

en.cppreference.com

 

modern c++이 된 C++11 에서는 template meta programming을 위하여 enable_if 가 사용되었고, c++17에서는 if constexpr이 이것을 도와주었다.

C++20에서는 Concepts 이라는 개념이 도입되며 template meta programming을 좀 더 편하게, 좀 더 안전하게 사용할 수 있게 되었다.

 

 

 


사용법은 다음과 같다.

 

template <typename T>
concept myConcept = /*조건*/;

 

이렇게 내가 원하는 조건을 지정해 두고 해당 concept을 template에 작성하면 된다.

 

 

include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if_t<std::is_same_v<T, int>, void>
print(T t)
{
    std::cout << "print : " << t << std::endl;
}

int main()
{
    print(42);
//     print("Hello, world!");  // 컴파일 에러!
    return 0;
}

예시로, 위와 같은 코드가 있다고 하자.

print를 하는 코드이다. 다만 type int 일 때만 사용 가능하다. 해당 코드를 concept을 이용하여 다시 구현하면

 

 

 

#include <iostream>

template <typename T>
concept SameAsInt = std::is_same_v<T, int>;

template <SameAsInt T>
void print(T t)
{
    std::cout << "print : " << t << std::endl;
}

int main()
{
    print(42);
    // print("Hello, world!");  // 컴파일 에러!
    return 0;
}

이런 식으로 구현이 가능하다.

변수를 정하듯 template T의 조건을 미리 지정할 수 있고, 해당 조건을 원하는 곳에서 쉽게 사용이 가능하다.

 

 


또, concept과 requires를 이용하여 조금 더 다양한 일도 할 수 있다.

 

template <typename T>
concept printable = requires(T obj) {
    {obj.print()} -> std::convertible_to<void>;
};

printable 이라는 concept은 obj.print() 를 void type으로 암시적으로 변환시킬 수 있다. 라는 뜻이다.

이것을 잘 생각해 보면, obj라는 객체가 있고, 해당 객체가 print라는 함수를 수행한 결과가 void면 이 조건을 만족시킨다.

즉, obj가 void type의 print 함수를 가지고 있냐 없냐를 검사하는 concept이다!

 

 

 

#include <iostream>

template <typename T>
concept printable = requires(T obj) {
    {obj.print()} -> std::convertible_to<void>;
};

template <printable T>
void printclass(T obj) {
    obj.print();
}


class Aclass {
public:
    void print() {

    }
};

class Bclass {
public:
    int nothing() {

    }
};

int main()
{
    Aclass a;
    Bclass b;

    printclass(a);
    printclass(b);  // error!
    return 0;
}

 

위의 concept을 사용하여, 쉽게 print 함수를 가지고 있는 class만 인자로 받는 printclass 함수를 만들 수 있다.

 

 

 

반응형

'C++ > STL' 카테고리의 다른 글

[C++] Priority_queue  (0) 2023.06.04
[C++17] Optional  (0) 2023.05.28
[C++] std::async. launch policy  (0) 2023.04.20
[C++] std::async, std::thread (2)  (0) 2023.04.10
[C++] std::async, std::thread (1)  (0) 2023.04.09