Jump to content
  • Advertisement
Sign in to follow this  
nuclear123

The Curiously Recurring Template Pattern help

This topic is 2174 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I cannot for the life of me figure out what im doing wrong. I'm trying to implement CRTP/static polymorphism to avoid the cost of vtable using the following code


template <class Derived>
struct base
{
// some reason this function is not getting called
void implementation()
{
_asm int 3;
static_cast<Derived*>(this)->implementation();
// ...
}
};

struct derived : base<derived>
{
void implementation()
{
_asm int 3;
}
};

int main()
{
derived test;
test.implementation();
return 0;
}


the problem is it's always calling the derived classes member function without first calling the base class.

Share this post


Link to post
Share on other sites
Advertisement
There's no reason for that code to call the base class' function. The derived function has 'hidden' the base version. Inside main, the compiler has the object '[font=courier new,courier,monospace]test[/font]', which is knows is of type '[font=courier new,courier,monospace]derived[/font]'. When you write '[font=courier new,courier,monospace]test.implementation[/font]' it first looks for that name in [font=courier new,courier,monospace]derived[/font], and finds it. If it didn't find the name there, it would continue looking for it in [font=courier new,courier,monospace]base[/font].

If you instead wrote:derived test;
base<Derived>* polymorphic = &test;
polymorphic->implementation();
Then the compiler only knows that '[font=courier new,courier,monospace]polymorphic[/font]' is of type '[font=courier new,courier,monospace]base<Derived>[/font]', so it looks for the name '[font=courier new,courier,monospace]implementation[/font]' inside [font=courier new,courier,monospace]base<Derived>[/font] first, and calls that function (which then should correctly use CRTP to call the [font=courier new,courier,monospace]derived[/font] version).

[edit] Also, you're using private inheritance, which hides the base function from public view in derived. Edited by Hodgman

Share this post


Link to post
Share on other sites
so in other words CRTP would be correctly used like the following



template <class Derived>
struct base
{
public:
// some reason this function is not getting called
void implementation()
{
_asm int 3;
static_cast<Derived*>(this)->implementation();
// ...
}
};

struct derived : base<derived>
{
void implementation()
{
_asm int 3;
}
};

int main()
{
base<derived> test;
test.implementation();
return 0;
}


I'm still a little confused one one thing. What causes this to be better performance than VTABLE referencing? to me i still see levels of indirection to get to the derived classes function from the base class Edited by nuclear123

Share this post


Link to post
Share on other sites
so in other words CRTP would be correctly used like the following
No, now your [font=courier new,courier,monospace]static_cast[/font] is completely bogus -- [font=courier new,courier,monospace]this[/font] is not a [font=courier new,courier,monospace]derived[/font], so performing that cast is undefined.
There was nothing wrong with your original version.
What causes this to be better performance than VTABLE referencing? to me i still see levels of indirection to get to the derived classes function from the base class
They're used for different purposes. Regular virtual functions are for when you need to be able to resolve the polymorphic type dynamically at runtime. Static-polymorphism is used where you can resolve the polymorphic type at compile time.

You can't just take a system that's built around runtime polymorphism and convert it to use compile-time polymorphism. It seems your misunderstanding is based around the purpose of the pattern, not how to implement it.

[edit]To illustrate a use case, consider the code:template<class T> void DoStuff( base<T>& test )
{
test.implementation();
}

derived test;
DoStuff(test);
In the above code, the DoStuff function can be written without knowing anything about the Derived class (including it's header, etc). It's only when you call the DoStuff function that the polymorphism is resolved (statically, at compile time).

A good compiler will completely optimise out the overhead of the [font=courier new,courier,monospace]base[/font] class, making it as efficient as if DoStuff was calling [font=courier new,courier,monospace]derived[/font] functions directly. The advantage is just in encapsulation / implementation-hiding / good code separation, where DoStuff can be written without any knowledge of the type that it's really operating on. Edited by Hodgman

Share this post


Link to post
Share on other sites
There's no reason to use pointers, references work just fine; for instance:
[source lang="cpp"]
Derived d;
d.interface(); // Prints "Derived implementation"

Base&lt;Derived&gt; & statically_polymorphic = d;
statically_polymorphic.interface(); // Prints "Derived implementation" as well

[/source]
See: http://ideone.com/P7Bmt

For more examples to help understand the use, see also:
http://en.wikibooks....emplate_Pattern
http://eli.thegreenp...e-pattern-in-c/
http://accu.org/index.php/journals/296 Edited by Matt-D

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!