가상 멤버 함수의 오버 헤드를 피하기 위해 C ++에서 CRTP를 어떻게 사용할 수 있습니까?
가상 멤버 함수의 오버 헤드를 피하기 위해 C ++에서 CRTP를 어떻게 사용할 수 있습니까?
답변:
두 가지 방법이 있습니다.
첫 번째는 유형의 구조에 대해 인터페이스를 정적으로 지정하는 것입니다.
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {
void foo(); // required to compile.
};
struct your_type : base<your_type> {
void foo(); // required to compile.
};
두 번째는 reference-to-base 또는 pointer-to-base 관용구를 사용하지 않고 컴파일 타임에 연결하는 것입니다. 위의 정의를 사용하면 다음과 같은 템플릿 함수를 가질 수 있습니다.
template <class T> // T is deduced at compile-time
void bar(base<T> & obj) {
obj.foo(); // will do static dispatch
}
struct not_derived_from_base { }; // notice, not derived from base
// ...
my_type my_instance;
your_type your_instance;
not_derived_from_base invalid_instance;
bar(my_instance); // will call my_instance.foo()
bar(your_instance); // will call your_instance.foo()
bar(invalid_instance); // compile error, cannot deduce correct overload
따라서 함수에서 구조 / 인터페이스 정의와 컴파일 타임 유형 추론을 결합하면 동적 디스패치 대신 정적 디스패치를 수행 할 수 있습니다. 이것이 정적 다형성의 본질입니다.
not_derived_from_base
에서 파생되지 않았 음 을 강조하고 싶습니다 ...base
base
나는 CRTP에 대한 적절한 토론을 찾고있었습니다. Todd Veldhuizen의 Techniques for Scientific C ++ 는이 (1.3) 및 표현식 템플릿과 같은 다른 많은 고급 기술에 대한 훌륭한 리소스입니다.
또한 Google 도서에서 Coplien의 원본 C ++ Gems 기사 대부분을 읽을 수 있음을 발견했습니다. 아마도 그럴 수도 있습니다.
dynamic_cast
또는 가상 메서드 가 필요 합니다.
나는 CRTP 를 찾아야했다 . 그러나 그렇게 한 후 Static Polymorphism 에 대한 몇 가지 사항을 발견했습니다 . 이것이 귀하의 질문에 대한 대답이라고 생각합니다.
그것은 밝혀 ATL은 매우 광범위하게이 패턴을 사용합니다.
이 Wikipedia 답변에는 필요한 모든 것이 있습니다. 즉:
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
이게 실제로 얼마나 당신을 사는지 모르겠지만. 가상 함수 호출의 오버 헤드는 다음과 같습니다 (물론 컴파일러에 따라 다름).
CRTP 정적 다형성의 오버 헤드는 다음과 같습니다.