Friday, 15 June 2012

c++ - CRTP Dispatch in C++11 -



c++ - CRTP Dispatch in C++11 -

say have next code:

template <class derived> class base of operations { public: virtual void foo_impl() = 0; void foo() { static_cast<derived*>(this)->foo_impl(); //a (*static_cast<derived*>(this)).foo_impl(); //b } }; class derived : public base<derived> { private: void foo_impl() { bar(); } };

a few questions:

will line generate virtual function call? although bulk of can find on net recommends doing things way, me don't see how compiler can static dispatch considering pointer derived still point object of type derived2 derived2 : public derived.

does line b prepare issue brought in previous point (if applicable)? seems would, considering phone call not on pointer more , using *. avoid virtual function call. if compiler treats dereferenced cast reference type, still generate virtual function call... in case, workaround?

does adding c++11 final keyword foo_impl() alter how compiler deed in either (or other relevant) case?

will line generate virtual function call?

yes. foo_impl() virtual , derived overrides it. though foo_impl() in derived not explicitly tagged virtual, in base of operations class, , plenty create virtual function.

does line b prepare issue brought in previous point (if applicable)?

no. not matter if phone call on pointer or on reference: compiler still won't know whether invoking function foo_impl() on instance of class derives from derived, or on direct instance of derived. thus, phone call performed through vtable.

to see mean:

#include <iostream> using namespace std; template <class derived> class base of operations { public: virtual void foo_impl() = 0; void foo() { static_cast<derived*>(this)->foo_impl(); (*static_cast<derived*>(this)).foo_impl(); } }; class derived : public base<derived> { public: void foo_impl() { cout << "derived::foo_impl()" << endl; } }; class morederived : public derived { public: void foo_impl() { cout << "morederived::foo_impl()" << endl; } }; int main() { morederived d; d.foo(); // output "morederived::foo_impl()" twice }

finally:

does adding c++11 final keyword foo_impl() alter how compiler deed in either (or other relevant) case?

in theory, yes. final keyword create impossible override function in subclasses of derived. thus, when performing function phone call foo_impl() through pointer derived, compiler could resolve phone call statically. however, best of knowledge, compilers not required c++ standard.

conclusion:

in case, believe want not declare foo_impl() function @ in base of operations class. case when utilize crtp. additionally, have declare class base<derived> friend of derived if want access derived's private function foo_impl(). otherwise, can create foo_impl() public.

c++ templates c++11 crtp

No comments:

Post a Comment