I suspect I can't do this directly using a PIMPL pattern. Is it possible to have a smart pointer to a template class? I have not been able to compile by turning knobs on the shared_ptr declaration.
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
Under Visual Studio 2008: "error C2065: 'T' : undeclared identifier". I receive a similar error under GCC. If I un-parameterize FooImpl (so that FooTempl inherits from FooImpl), the code will compile.
I suspect I can't paramaterize the smart pointer, but I could be wrong.
EDIT: The second Visual Studio error is more telling: "error C3203: 'FooImpl' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type"
Jeff
I'm not entirely certain what you are trying to accomplish, but does this help?
Try 1:
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
template<class C>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<C> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
Try 2:
// ============Foo.h ============
// Forward declare the implementation
class FooImplBase;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImplBase > m_impl;
};
// ============FooImpl.h ============
class FooImplBase {
public:
virtual void AnAPI();
virtual int AnotherAPI();
};
template <typename T>
class FooImpl : public FooImplBase
{
...
};
The code you have posted cannot compile since T does not mean anything in the context of Foo. The compiler expects a type called T here which does not exist there... Not entirely sure what you are trying to accomplish, but wouldn't the following solve your problem?
// ============Foo.h ============
class FooImplBase {
virtual void WhateverFooImplIsSupposedToDo() = 0;
};
template <typename T> class FooImpl : public FooImplBase {
T mInstance;
public:
FooImpl(T const & pInstance) : mInstance(pInstance) {}
virtual void WhateverFooImplIsSupposedToDo()
{
// implementation which deals with instances of T
}
};
class Foo
{
public:
Foo getInstance(const string& fooType) {
// use m_impl->WhateverFooImplIsSupposedToDo...
}
template < class T >
Foo( T const & pInstance ) : m_impl(new FooImpl<T>(pInstance)) {}
private:
shared_ptr< FooImplBase > m_impl;
};
You're doing it right, just make sure T is defined. This compiles for me on MSVC++ 2010:
#include <memory>
using namespace std;
template<class T>
class Blah {
public:
Blah() { }
};
class Foo {
public:
shared_ptr<Blah<int>> ptr;
Foo() : ptr(new Blah<int>()) { }
};
If you're on an older compiler that hasn't incorporated this feature of C++11 yet, change
shared_ptr<Blah<int>> ptr;
To
shared_ptr<Blah<int> > ptr;
So the compiler doesn't think the >> is a right shift. C++11 doesn't have this problem though.
I don't know in advance I am going to have a Blah, only a Blah.
From the language point of view, Blah<T> is meaningless because T doesn't exist. Depending on what you're exactly trying to do, you can
make Foo a template, too, so that you can declare a template parameter T:
template<typename T>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
which 'fixes' the choice of T when you declare a variable of type Foo<T>;
or make FooImpl explicitly derive from a common base:
class FooBase {
// need to define the interface here
};
// this is a class definition whereas previously you only needed a declaration
template<typename T>
class FooImpl: public FooBase {
// definition here
};
class Foo
{
public:
Foo getInstance(const string& fooType);
// we needed the definition of FooImpl for this member
// in addition this member is quite obviously a template
template<typename T>
void
set(FooImpl<T> const& foo)
{
m_impl.reset(new FooImpl<T>(foo));
}
// not a member template!
void
use()
{
// any use of m_impl will be through the FooBase interface
}
private:
shared_ptr<FooBase> m_impl;
};
where for a given Foo instance any kind of FooImpl<T> can be set dynamically and then used through the FooBase interface. This is a kind of type erasure as it's called in the C++ world.
We can use templates to write a generic smart pointer class. Following C++ code demonstrates the same. We don't need to call delete 'ptr', when the object 'ptr' goes out of scope, destructor for it is automatically.
#include<iostream>
using namespace std;
// A generic smart pointer class
template <class T>
class SmartPtr
{
T *ptr; // Actual pointer
public:
// Constructor
explicit SmartPtr(T *p = NULL) { ptr = p; }
// Destructor
~SmartPtr() {
cout <<"Destructor called" << endl;
delete(ptr);
}
// Overloading dereferncing operator
T & operator * () { return *ptr; }
// Overloding arrow operator so that members of T can be accessed
// like a pointer (useful if T represents a class or struct or
// union type)
T * operator -> () { return ptr; }
};
int main()
{
SmartPtr<int> ptr(new int()); // Here we can create any data type pointer just like 'int'
*ptr = 20;
cout << *ptr;
return 0;
}
out put:
20
Destructor called
Related
I have a sprite class, which has a templatised data member. It holds an object, which has a pointer to this specialised sprite template class.
That object requires a forward declaration of my sprite class, but since sprite is a template class, I need to include the full header. Therefore I get a cyclic dependancy which I am unable to figure out
Sprite.h
#include "myclass.h"
template<typename SpriteType, typename = typename std::enable_if_t<std::is_base_of_v<sf::Transformable, SpriteType> && std::is_base_of_v<sf::Drawable, SpriteType>>>
class Sprite {
public:
SpriteType s;
myclass<SpriteType>;
Sprite() {
}
auto foo() {
return s;
}
private:
};
myclass.h
#include "Sprite.h"
//a sprite of type T, is going to create a myclass<Sprite<T>>, a pointer of the Sprite<T> is held in myclass.
template<typename T>
class myclass
{
public:
std::shared_ptr<Sprite<T>> ptr;
myclass() {
}
private:
};
How could I solve this cyclic dependency?
So in summary:
-Sprite is a template class.
-Sprite holds an object to another class. This other class holds a pointer to my this templated sprite class.
-This gives me a cyclic dependency, since both classes are now templates, and need to have their implementations written in their header files.
Simplified decoupling, based on #Taekahns solution.
template<typename T>
class myclass
{
public:
std::shared_ptr<T> ptr;
myclass() {
}
private:
};
template<typename SpriteType, typename = typename std::enable_if_t<std::is_base_of_v<sf::Transformable, SpriteType> && std::is_base_of_v<sf::Drawable, SpriteType>>>
class Sprite {
public:
SpriteType s;
// DO NOT PASS SpriteType here, put the whole Sprite<SpriteType>
myclass<Sprite<SpriteType>> t;
Sprite() {
}
auto foo() {
return s;
}
private:
};
One of the great thing about templates is breaking type dependencies.
You could do something like this. Simplified for readability.
template<typename T>
class myclass
{
public:
std::shared_ptr<T> ptr;
myclass() {
}
private:
};
template<typename SpriteType, typename = std::enable_if_t<std::is_base_of_v<base_class, SpriteType>>>
class Sprite {
public:
SpriteType s;
myclass<Sprite<SpriteType>> t;
Sprite() {
}
auto foo() {
return s;
}
private:
};
That is one of many options.
Another option is to use an interface. i.e. a pure virtual base class that isn't a template.
Example:
I think something like this should do it. Starting to get a hard to follow though.
class base_sprite
{
public:
virtual ~base_sprite(){};
virtual int foo() = 0;
};
template<typename T>
class myclass
{
public:
std::shared_ptr<base_sprite> ptr;
myclass() : ptr(std::make_shared<T>())
{
};
};
template<typename SpriteType>
class Sprite : public base_sprite{
public:
myclass<Sprite<SpriteType>> l;
int foo() override {return 0;};
};
Let's say I have the following template class:
template<typename T>
class A
{
public:
// Lots of functions...
void someFunc(T obj)
{
// T must implement this function in order to be usable within class A.
obj.interfaceFunc();
}
};
This works fine, as the object I will use with the template class implements interfaceFunc().
However, if I pass a pointer to the template class then the compilation fails because the dereference syntax is incorrect. Because the template class contains a lot of other functions that I don't want to copy/paste into another partial specialisation if I can possibly help it, I have changed my class definition as follows:
template<typename T>
class A
{
public:
// Lots of functions...
virtual void virtualHelperFunction(T* obj)
{
// We should never be here in the base class.
assert(false);
}
void someFunc(T obj)
{
// Call the virtual function.
virtualHelperFunction(&obj);
}
};
// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
However, when virtualHelperFunction() is called, on an instance of B but when inside the someFunc() function of the parent A, it hits the assertion error.:
B<SomeObject> instance;
instance.someFunc(SomeObject()); // Assertion failure.
I've tried messing around with function pointers to solve this but I'm still fairly new to them, and the non-static pointer syntax confused me a bit. I'm assuming one could define a member pointer to the virtualHelperFunction() which is set to point to the base class version in A's constructor, but which is then overwritten in B's constructor to point to B's function. If so, would anyone be able to demonstrate the correct syntax to do this?
Thanks.
EDIT: If context is needed, the template class is an octree node which stores a hash table of type T. The interface function required is that the object can return a bounding box, in order for recursive insertion to function depending on whether the object's bounds intersect with the tree node's bounds.
https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc/worldculltreenode.h
https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc/worldculltreenode.tcc
This seems way too complicated. Why specialize the entire class if you just need one tiny bit specialized? All you need is a small utility that says "dereference this if it's a pointer, otherwise leave it alone". It could look like this:
template <typename T>
T& deref_if_pointer(T& t) { return t; }
template <typename T>
T& deref_if_pointer(T* t) { return *t; }
// ...
void someFunc(T obj) {
deref_if_pointer(obj).interfaceFunc();
}
You can easily extend deref_if_pointer to various smart pointers as well; just add another overload.
I'm not really sure what it is that you want to accomplish, so I'll have to guess. In what way does the following not satisfy your problem?
class A
{
public:
// Lots of functions...
void someFunc(T* obj)
{
// T must implement this function in order to be usable within class A.
obj->interfaceFunc();
}
void someFunc(T obj)
{
// T must implement this function in order to be usable within class A.
obj.interfaceFunc();
}
};
If you want to do it that way, then you need to take a reference instead of a pointer in the first partial specialization:
template<typename T>
class A
{
public:
// Lots of functions...
virtual void virtualHelperFunction(T* obj)
{
// We should never be here in the base class.
assert(false);
}
void someFunc(T obj)
{
// Call the virtual function.
virtualHelperFunction(&obj);
}
};
// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
// ...
virtual void virtualHelperFunction(T& obj)
{
obj.interfaceFunc();
}
};
// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
Your code doesn't compile. template<typename T*> is illegal and you do not have any partial specializations as you claim.
This works:
template<typename T>
class A
{
public:
// Lots of functions...
virtual void virtualHelperFunction(T* obj)
{
// We should never be here in the base class.
assert(false);
}
void someFunc(T obj)
{
// Call the virtual function.
virtualHelperFunction(&obj);
}
};
// Unspecialized template
template<typename T>
class B : public A<T>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
// Partial specialisation
template<typename T>
class B<T*> : public A<T*>
{
public:
// ...
virtual void virtualHelperFunction(T** obj)
{
(*obj)->interfaceFunc();
}
};
int main() {
B<SomeObject> instance1;
instance1.someFunc(SomeObject());
B<SomeObject*> instance2;
SomeObject x;
instance2.someFunc(&x);
}
Well this has been giving me grief...
#include <iostream>
class InterfaceClass
{
public:
void test()
{
std::cout<<"Hello there.\n";
}
};
template <class T>
class TemplateClass
{
public:
T t;
};
class TestClass: public InterfaceClass
{};
class TestInheritor
{
public:
TemplateClass < InterfaceClass >* templateInherit;
InterfaceClass* normalInherit;
void test()
{
normalInherit->test();
templateInherit->t.test();
}
};
int main (int nargs, char ** arg)
{
TestInheritor ti;
ti.normalInherit = new TestClass; // THIS ONE COMPILES OKAY.
//ti.templateInherit = new TemplateClass <TestClass>; // COMPILE ERROR.
// THIS WORKS THOUGH
TemplateClass <TestClass> * tempClass = new TemplateClass <TestClass>;
ti.templateInherit=(TemplateClass <InterfaceClass>*)tempClass; // WHY DO I HAVE TO EXPLICITLY CAST?
// OUTPUT WORKS AS EXPECTED.
ti.test();
return 0;
}
The normal inheritance example works just fine. The TestClass is automatically converted to a InterfaceClass. However, with the template example, it gives a compile error:
error: cannot convert 'TemplateClass<TestClass>*' to 'TemplateClass<InterfaceClass>*' in assignment
In my mind, it is obvious that you can convert TemplateClass<TestClass>* to TemplateClass<InterfaceClass>*... So what am I missing here?
I can fix it by explicitly casting the template class to the base class, I am able to use the inherited test() function without any problem... So why am I required to explicitly cast the template class?
Sorry if that's confusing... It's hard for me to explain this problem.
Okay, I understand the issue a little more. I have decided to add a template to TestInheritor like so:
template <class T2>
class TestInheritor
{
public:
TemplateClass < T2 >* templateInherit;
InterfaceClass* normalInherit;
void test()
{
normalInherit->test();
templateInherit->t.test();
}
};
int main (int nargs, char ** arg)
{
TestInheritor <TestClass> ti;
ti.normalInherit = new TestClass;
ti.templateInherit = new TemplateClass <TestClass>;
ti.test();
return 0;
}
Probably not the perfect solution, but it works for my purposes.
Ah, and I see your solution:
#include <iostream>
class InterfaceClass
{
public:
void test()
{
std::cout<<"Hello there.\n";
}
};
class TestClass: public InterfaceClass
{};
template <class T>
class TemplateClass
{
public:
T t;
};
template<>
class TemplateClass<TestClass> : public TemplateClass<InterfaceClass>
{
public:
};
class TestInheritor
{
public:
TemplateClass < InterfaceClass >* templateInherit;
InterfaceClass* normalInherit;
void test()
{
normalInherit->test();
templateInherit->t.test();
}
};
int main (int nargs, char ** arg)
{
TestInheritor ti;
ti.normalInherit = new TestClass;
ti.templateInherit = new TemplateClass <TestClass>;
ti.test();
return 0;
}
Consider
class Base
{};
class Derived : public Base
{};
template<typename T>
class TemplateClass
{};
Contrary to what you might think, TemplateClass<Derived> is not a TemplateClass<Base> in the sence of inheritance, so pointers to the former can't be implicitly converted to pointers of the later.
So why does explicitly casting a pointer to TemplateClass<Derived> to a pointer of TemplateClass<Base> compile? Because any pointer of a certain type may be explicitly cast to any pointer of any other type, however there are no guarantees the conversion is valid! You could for instance just as well write
int* i = (int*) new TemplateClass<Derived>;
and it would compile just fine, even though it is clearly an invalid conversion.
Now why does your example work? Sheer luck. At the point a pointer containing an address obtained through an invalid pointer cast gets dereferenced, the program becomes invalid and its bahavior undefined. Anything can happen, including doing what you would expect.
If you want TemplateClass<Derived> to be a TemplateClass<Base> in the sence of inheritance, you can define an specialization of TemplateClass<> stating this relationship explicitly, like the following:
template<>
class TemplateClass<Derived> : public TemplateClass<Base>
{};
I have two classes, lets call them SomeClass and OtherClass.
SomeClass is templated:
template <typename T> class SomeClass
{
public:
SomeClass (const T& value);
};
OtherClass isn't templated, but uses SomeClass.
class OtherClass
{
public:
OtherClass (const SomeClass& c, const std::string s);
};
They are supposed to be called this way:
SomeClass<int> some(5);
OtherClass other(some, "hello, world!");
other.doSomethingWithSome();
...Obviously, this will fail to compile since the compiler needs to know SomeClass' type...
Unfortunately for me, the type of SomeClass can be pretty much anything (though the number of actual types used are limited, just unrelated), and might frequently change while in development. (I know, I know, I suppose I really could use SomeClass' type and pass it to a templated OtherClass, but its quite a tedious job since there are some many instances; also, I'd like to pretend neither class knows about the other's workings. :) )
The question is simple: how can I use this syntax? (Without having to templatize OtherClass.)
An obvious answer is that you could make SomeClass inherit from a non-template abstract class :
template <typename T>
class SomeClass : public SomeAbstractBase
{
/* ... */
};
And in turn, OtherClass will work on SomeAbstractBase :
class OtherClass
{
public:
OtherClass (const SomeAbstractBase& c, const std::string s);
};
You're not really giving enough to say for sure that this in an appropriate solution, but it might be. In the end, if you have no problem writing SomeAbstractBase (ie: you easily manage to identify what's common to all SomeClass<T>), than it's probably the way to go.
You use type hiding:
class OtherClass
{
public:
template < typename T >
OtherClass(SomeClass<T> const& c, std::string const& s)
: pimpl(new impl<T>(c))
, str(s)
{}
void doSomething() { pimpl->doSomething(str); }
private:
struct impl_base { virtual ~impl_base() {} virtual void doSomething(std::string) { ... }};
template < typename T >
struct impl : impl_base
{
impl(T const& )...
};
scoped_ptr<impl_base> pimpl;
};
You will either need to templatize OtherClass -or- specialize the OtherClass constructor to accept the types of SomeClass you need to pass.
// Otherclass can take objects of any type now
template <typename T> class OtherClass
{
public:
OtherClass(SomeClass<T>& someclass..);
};
// or
class OtherClass
{
// specialize the otherclass constructor
OtherClass(SomeClass<int> someclass ..)
}
It's not clear exactly what you're trying to do. But how about a templated constructor?
class OtherClass {
public:
template <typename T> OtherClass(const SomeClass<T>& c, const std::string& s);
// ...
};
Of course this won't work if, for example, OtherClass needs a member of type SomeClass<T>.
Use both compile-time (templates) and runtime polymorphism (virtuals):
class MyBase {
public:
virtual void foo() = 0;
}
template <class T>
class SomeClass : public MyBase {
public:
void foo () {
// do T-specific stuff
}
}
OtherClass then takes a MyBase* and OtherClass::doSomethingWithSome invokes it virtual foo method.
I have two classes that depend on each other:
class Foo; //forward declaration
template <typename T>
class Bar {
public:
Foo* foo_ptr;
void DoSomething() {
foo_ptr->DoSomething();
}
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};
When I compile it in g++, it was giving error of "Invalid use of incomplete type", but it was compiled nicely in MSVC 10.
Is it possible to solve this problem while keeping the declaration and definition in one header file? (no cpp files)
If this is not allowed in the standard, so is this one of the MSVC "bug" or "feature"?
Yes, just move the method definitions out of the class definition:
class Foo; //forward declaration
template <typename T>
class Bar {
public:
Foo* foo_ptr;
void DoSomething();
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};
// Don't forget to make the function inline or you'll end up
// with multiple definitions
template <typename T>
inline void Bar<T>::DoSomething() {
foo_ptr->DoSomething();
}
See this page:
What is the best way to deal with co-dependent classes in C++?
It should clear up the problem and provides a couple nice solutions.
It works when you replace Foo* foo_ptr; by the template parameter T so that you get T* foo_ptr;. In this foo_ptr does not necessarily have to be a pointer or be predefined.
template <typename T>
class Bar {
public:
T foo;
void DoSomething() {
foo.DoSomething();
}
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};