mardi 27 mai 2014

c ++ - programme de formation itinérante pour éviter le polymorphisme dynamique - Stack Overflow


How can I use CRTP in C++ to avoid the overhead of virtual member functions?




There are two ways.


The first one is by specifying the interface statically for the structure of types:


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.
};

The second one is by avoiding the use of the reference-to-base or pointer-to-base idiom and do the wiring at compile-time. Using the above definition, you can have template functions that look like these:


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

So combining the structure/interface definition and the compile-time type deduction in your functions allows you to do static dispatch instead of dynamic dispatch. This is the essence of static polymorphism.




I've been looking for decent discussions of CRTP myself. Todd Veldhuizen's Techniques for Scientific C++ is a great resource for this (1.3) and many other advanced techniques like expression templates.


Also, I found that you could read most of Coplien's original C++ Gems article at Google books. Maybe that's still the case.




I had to look up CRTP. Having done that, however, I found some stuff about Static Polymorphism. I suspect that this is the answer to your question.


It turns out that ATL uses this pattern quite extensively.




This Wikipedia answer has all you need. Namely:


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();
};

Although I don't know how much this actually buys you. The overhead of a virtual function call is (compiler dependent, of course):



  • Memory: One function pointer per virtual function

  • Runtime: One function pointer call


While the overhead of CRTP static polymorphism is:



  • Memory: Duplication of Base per template instantiation

  • Runtime: One function pointer call + whatever static_cast is doing




By means of curiously recurring template pattern you can implement the static polymorphism. You can find an example on wikipedia.



How can I use CRTP in C++ to avoid the overhead of virtual member functions?



There are two ways.


The first one is by specifying the interface statically for the structure of types:


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.
};

The second one is by avoiding the use of the reference-to-base or pointer-to-base idiom and do the wiring at compile-time. Using the above definition, you can have template functions that look like these:


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

So combining the structure/interface definition and the compile-time type deduction in your functions allows you to do static dispatch instead of dynamic dispatch. This is the essence of static polymorphism.



I've been looking for decent discussions of CRTP myself. Todd Veldhuizen's Techniques for Scientific C++ is a great resource for this (1.3) and many other advanced techniques like expression templates.


Also, I found that you could read most of Coplien's original C++ Gems article at Google books. Maybe that's still the case.



I had to look up CRTP. Having done that, however, I found some stuff about Static Polymorphism. I suspect that this is the answer to your question.


It turns out that ATL uses this pattern quite extensively.



This Wikipedia answer has all you need. Namely:


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();
};

Although I don't know how much this actually buys you. The overhead of a virtual function call is (compiler dependent, of course):



  • Memory: One function pointer per virtual function

  • Runtime: One function pointer call


While the overhead of CRTP static polymorphism is:



  • Memory: Duplication of Base per template instantiation

  • Runtime: One function pointer call + whatever static_cast is doing



By means of curiously recurring template pattern you can implement the static polymorphism. You can find an example on wikipedia.


0 commentaires:

Enregistrer un commentaire