1 minute read

1. CRTP

“이상한 재귀 템플릿 패턴(Curiously Recurring Template Pattern)” 이라고 불린다! 디자인 패턴이라기보다는 C++에서 주로 사용하는 코드 패턴이라고 생각하자.


1
2
3
4
5
6
struct Foo : SomeBase<Foo>
{
    ...
}

1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename Derived>
struct SomeBase
{
    void foo()
    {
        for(auto& item : *static_cast<Derivec*>(this))
        {
            ...
        }
    }
}


위 코드와 같이 자기 자신을 베이스 클래스의 템플릿 인자로 상속받는다.

자기 자신을 상속하게 되면 베이스 클래스의 구현부에서 타입이 지정된 this 포인터를 사용할 수 있다.

일반적으로 상위 클래스는 서브 클래스의 객체를 순회할 수 없지만, CRTP를 적용하면 this를 서브 클래스 타입으로 캐스팅할 수 있다.


2. 첨가(Mixin) 상속

클래스 인자를 정의할 때 자기 자신을 템플릿 인자로 할 수 있다.

1
2
3
4
5
6
template <typename T> struct Mixin : T
{
    ...
}

이러한 방식을 첨가 상속(mixin inheritance)이라고 한다.

첨가 상속을 이용하면 계층적으로 여러 타입을 형성할 수 있다.

eg) Foo<Bar<Baz>> x 와 같은 변수를 선언하면 새로운 타입 FooBarBaz를 구현하지 않고 세 가지 타입의 속성을 가지게 할 수 있다!


3. 속성

일반적으로 C++에서 속성을 표현하는 방법은 아래와 같다.

1
2
3
4
5
6
7
8
9
class Person
{
    int age;
public:
    int get_age() const { return age; }
    void set_age(int value) { age = value; }
};


C++ 자체의 기능으로 속성을 지원하지 않지만, 대부분의 컴파일러에서 비표준적인 방법으로 속성을 지원한다. 아래와 같이 코드를 작성하면 자동으로 get/set 메서드가 호출된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person
{
    int age_;
public:
    int get_age() const { return age_; }
    void set_age(int value) { age_ = value; }
    __declspec(property(get=get_age, put=set_age)) int age;
}

int main()
{
    Person p;
    p.age = 20;     // p.set_age(20)
}

Leave a comment