(C++ : Template) CRTP : 자녀클래스의 이름(정보)을 알고 싶을때

Posted by : at

Category : Cpp


  • Curiously Recurring Template Pattern(신기하게도 언급되는 템플릿 패턴)
class Base
{
    // Base에서는 Derived의 이름을 알 수 없다.
    // 알게 하고 싶다면?? -> CRTP
};

class Derived : public Base
{

};

int main()
{
    Derived d;
}
template<typename T> class Base
{
public:
    Base()
    {
        cout << typeid(T).name() << endl;
    }
};

class Derived : public Base<Derived>        // 파생클래스를 만들때 이름을 전달해준다.
{

};

int main()
{
    Derived d;
}

어디에 쓰면 좋을까?

#include <iostream>
using namespace std;

class Window
{
public:
    void msgLoop()
    {
        OnClick();
    }
    void OnClick() { cout << "Window OnClick" << endl; }
};

class FrameWindow : public Window
{
public:
    void OnClick() { cout << "FrameWindow Window OnClick" << endl; }
};

int main()
{
    FrameWindow fw;
    fw.msgLoop();   // Window::OnClick가 호출된다
    // 원하는 것은 FrameWindow::OnClick 호출되는 것
    // 물론 virtual선언하면 되지만 ... 오버헤드가 커진다.
}
template<typename T> class Window
{
public:
    void msgLoop()
    {
        //OnClick();
        static_cast<T*>(this)->OnClick();
    }
    void OnClick() { cout << "Window OnClick" << endl; }
};

class FrameWindow : public Window<FrameWindow>
{
public:
    void OnClick() { cout << "FrameWindow Window OnClick" << endl; }
};

Example - CRTP를 이용해서 singleton 만들어보자.

class Cursor
{
private:
    Cursor() {}
public:
    Cursor(const Cursor& c) = delete;
    void operator=(const Cursor& c) = delete;

    static Cursor& getInstance()
    {
        static Cursor instance;
        return instance;
    }
};

int main()
{
    // Cursor c1, c2;
    Cursor& c1 = Cursor::getInstance();
    Cursor& c2 = Cursor::getInstance();
    // 같음
}
class Mouse
{
    // Mouse도 Singleton화 하고 싶다면?
};
class Mouse : public Singleton  // 이렇게?
{
};
template<typename T> class Singleton
{
protected:
    Singleton() {}
public:
    Singleton(const Singleton& c) = delete;
    void operator=(const Singleton& c) = delete;

    static T& getInstance()
    {
        static T instance;
        return instance;
    }
};

class Mouse : public Singleton<Mouse>
{
};

int main()
{
    Mouse& m = Mouse::getInstance();
}

Example

#include <iostream>
using namespace std;

class Object
{
public:
    static int cnt;

    Object() { ++cnt; }
    ~Object() { --cnt; }

    static int getCount() { return cnt; }
};
int Object::cnt = 0;

class Mouse
{
    // Mouse에서도 객체의 개수를 관리하고 싶다면??
};

int main()
{
    Object c1, c2;
    cout << c1.getCount() << endl;
}
class Mouse : Object
{
};

class Keyboard : Object
{
};

int main()
{
    Mouse m1, m2;
    Keyboard k1, k2;
    cout << m1.getCount(); << endl; // 4 -> 잉??
}
template<typename T> class Object
{
public:
    static int cnt;

    Object() { ++cnt; }
    ~Object() { --cnt; }

    static int getCount() { return cnt; }
};
template<typename T> int Object::cnt = 0;

class Mouse : Object<Mouse>
{
};

class Keyboard : Object<Keyboard>
{
};

int main()
{
    Mouse m1, m2;
    Keyboard k1, k2;
    cout << m1.getCount(); << endl; // 2
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links