Jump to content
  • Advertisement
Sign in to follow this  
c4c0d3m0n

Templates [C++] - Why doesn't this work?

This topic is 3544 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

#include <boost/shared_ptr.hpp>

class Parent
{
  public:
    virtual void foo();
    int bar;
};

class Child : public Parent
{
  public:
    void foo() { bar++; };
    int bar;
};



template <Parent T>
boost::shared_ptr<T>
create()
{
    boost::shared_ptr<T> pointer( new T );
    return pointer;
}



int main()
{
    boost::shared_ptr<Parent> pointer = create<Child>();
    return 0;
}

temp.cpp:19: error: ‘class Parent’ is not a valid type for a template constant parameter
I always thought I could create a template of whatever I want, not just a class.. Could someone please explain why this is not allowed? What I basically want is a template that only allows classes inherited from Parent. How would I go on about this?

Share this post


Link to post
Share on other sites
Advertisement
Ok, there are two problems. The first problem is that non-type template parameters need to be either integral constants or a pointer or reference to an entity with external linkage, so you need to have a Parent * or Parent &. The second problem is that you aren't using it as a non-type template parameter, since you're trying to use Child as the template parameter. Basically, the way you're using it you should replace Parent with class or typename.

Share this post


Link to post
Share on other sites
Quote:
Original post by c4c0d3m0n
*** Source Snippet Removed ***

temp.cpp:19: error: ‘class Parent’ is not a valid type for a template constant parameter



I always thought I could create a template of whatever I want, not just a class.. Could someone please explain why this is not allowed?

What I basically want is a template that only allows classes inherited from Parent. How would I go on about this?


You need to change your code to:


template <class T>
boost::shared_ptr<T> create()
{
boost::shared_ptr<T> pointer(new T);
return pointer;
}

int main)
{
...
}

Share this post


Link to post
Share on other sites
Thanks for the quick replies!


@SiCrane:
I am not sure what you mean by "pointer or reference to an entity with external linkage" I do see now why the code wouldn't work anyway; Child is not of type Parent (the second issue you addressed).


@soconne:
The problem with that code is that it would also allow classes that are not inherited from Parent. How can I make it so only classes inherited from Parent are allowed as template parameter?

Share this post


Link to post
Share on other sites
The simplest way to restrict it to child classes of your Parent class would be to add a BOOST_STATIC_ASSERT() that Parent is a base of the template type. boost::type_traits' is_base_of would probably be the most straightforward way to ensure that.

Share this post


Link to post
Share on other sites
Hmm.. I seem to be very terible at finding good boost documentation through google, but I found an example on a mailing list. Still, I can't quite get it to work...


template <class T>
boost::shared_ptr<T>
create()
{
BOOST_STATIC_ASSERT(( boost::is_base_of<T, Parent>::value ));

boost::shared_ptr<T> pointer( new T );
return pointer;
}


rob@rob-laptop:~/Desktop$ g++ temp.cpp
temp.cpp: In function ‘boost::shared_ptr<T> create() [with T = Child]’:
temp.cpp:34: instantiated from here
temp.cpp:24: error: invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE<false>’

Share this post


Link to post
Share on other sites
In that case I get funky errors about the vtables in Parent ... oO

rob@rob-laptop:~/Desktop$ g++ temp.cpp
/tmp/ccWNjx4L.o: In function `Parent::Parent()':
temp.cpp:(.text._ZN6ParentC2Ev[Parent::Parent()]+0x4): undefined reference to `vtable for Parent'
/tmp/ccWNjx4L.o:(.rodata._ZTI5Child[typeinfo for Child]+0x8): undefined reference to `typeinfo for Parent'
collect2: ld returned 1 exit status



edit:
If I remove all the contents of the classes, it seems to work. Maybe something wasnt kosher with the using no::brain inheritance up there

Share this post


Link to post
Share on other sites
Quote:
Original post by c4c0d3m0n
@soconne:
The problem with that code is that it would also allow classes that are not inherited from Parent. How can I make it so only classes inherited from Parent are allowed as template parameter?


Oooohh, sorry, I should have read your post more carefully. One way to solve it is to use the dynamic_cast function.



class Parent { };
class Child : public Parent { };

template <typename P, typename T>
boost::shared_ptr<T>
create()
{
T* t = new T();
if (dynamic_cast<P*>(t) != 0)
return boost::shared_ptr(t);
else
// throw error or return 0
}



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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!