How do I cast between subclasses of shared_ptr? - c++

I'm subclassing std::shared_ptr and am trying to write a cast() method on the subclass so I can hide static_pointer_cast, but I can't get my code to compile. What am I missing?
Demo: http://ideone.com/nbPHbs
template<class T>
class Handle : public std::shared_ptr<T> {
public:
template<class ResultType>
inline Handle<ResultType>
cast() {
// Cast Handle to shared_ptr
auto T_sp = static_cast< std::shared_ptr<T> >(*this);
// Cast the data
auto ResultType_sp = std::static_pointer_cast<ResultType>(T_sp);
// Cast back to Handle
return static_cast< Handle<ResultType> >(ResultType_sp);
}
};
// Usage
struct Base {};
struct Child : public Base {};
auto child_ptr = Handle<Child>(new Child());
auto base_ptr = child_ptr.cast<Base>(); // Error with this
This is the Error message I get:
error: no matching function for call to 'Handle<Child>::Handle(Child*)'
auto child_ptr = Handle<Child>(new Child());
^
**EDIT
I'm using inheritance here because it was write-once/throw-away code that was originally template<T> using std::shared_ptr<T> Handle<T>; So, inheritance was the natural progression that required the least amount of code changes. Since it did look like this piece of code will stick around a little longer, I did switch to composition before posting this SO question, I just wanted to know why it wasn't compiling; I haven't done any c++ in a few years, so my skills are a little rusty.

This answer is skipping the discussion as to whether inheriting from std::shared_ptr is a good idea or not. I would though recommend reading such discussion before continuing further.
Now to your immediate problem:
If you really want to continue this route then what you are missing is the constructors.
The compiler is only creating a default constructor for you.
As the error message shows you need Handle<Child>::Handle(Child*).
The easiest way to get the needed constructors would be to reuse the ones from the base class:
template<class T>
class Handle : public std::shared_ptr<T> {
public:
using std::shared_ptr<T>::shared_ptr;
...

I dont see any advantage of inheriting shared_ptr here, its not worth the trouble imho. if you think std::static_pointer_cast is big and ugly, you can solve that by an inline function
template <typename TOUT, typename TIN>
inline std::shared_ptr<TOUT> cast(TIN in)
{
return std::static_pointer_cast<TOUT>(in);
}
// Usage
struct Base {};
struct Child : public Base {};
int main() {
std::shared_ptr<Child> child_ptr = std::make_shared<Child>();
std::shared_ptr<Base> base_ptr = cast<Base>(child_ptr); // Error with this
return 0;
}

Your class does not have any constructor, therefore, when you try to compile, it will miserably fail if you try to use a constructor with arguments.
If you wanted to inherit from shared_ptr (which I disencourage, because base destructor is not virtual and your program most likely will leak memory heavily) you should add this line in your class body:
using std::shared_ptr<T>::shared_ptr;

Related

Implicit downcast of shared_ptr in CRTP

I built a class Interface to be used with CRTP for static polymorphism and a Client class having a shared_ptr to the Interface. I would like to return from the Client the shared_ptr to the Implementation, something that I can (safely?) do through static_pointer_cast within the Client. Is there a way to allow an implicit downcasting from the shared_ptr to Interface to a shared_ptr to Implementation?
template<class Implementation>
struct Interface {
int foo() { return static_cast<Implementation*>(this)->fooimpl();}
};
template<class Implementation>
struct Client {
Client(std::shared_ptr<Implementation> const & pt) : pt_{pt} {}
std::shared_ptr<Interface<Implementation>> pt_;
std::shared_ptr<Implementation> getPt() {
//Can I avoid this static_pointer_cast?<
return std::static_pointer_cast<Implementation>(pt_);
}
};
One possible solution to avoid all this mess is to keep a shared_ptr to Implementation within the Client class. In this way, however, nowhere I am saying that Implementation in Client has the Interface.
template<class Implementation>
struct Client {
Client(std::shared_ptr<Implementation> const & pt) : pt_{pt} {}
std::shared_ptr<Implementation> pt_;
std::shared_ptr<Implementation> getPt() { return pt_;}
};
Is there a way to allow an implicit downcasting from the shared_ptr to Interface to a shared_ptr to Implementation?
Simple answer: No! As the compiler have no idea of the "reverse" inheritance, it can give you direct support for it. CRTP is a general pattern to work around the underlying problem. Here the downcast is hand coded but hidden behind the interface of the CRTP implementation.
The CRTP is because I want Client to use foo() and at the same time independent of the implementation
As you get it as a compile time implementation, it is not really independent at the moment. You will see it latest, if you want point to something of that CRTP type.
The shared_ptr is because the Implementation may be shared among Clients
Your idea have a circular problem!
If you write as given in your example:
template
struct Client {
Client(std::shared_ptr const & pt) : pt_{pt} {}
std::shared_ptr pt_;
std::shared_ptr getPt() { return pt_;}
};
the code which calls getPt() must know the type of the returned pointer! Even if you use auto you will get the type of the returned pointer. So you simply can't hide it from your using code at all.
I ended up just putting a shared_ptr to the Implementation as class member and added a "static_assert + is_base_of " to insure this.
Seems to be also a circular problem.
If you write:
template < typename T>
class CRTP: public T
{
public:
void Check()
{
static_assert( std::is_base_of_v < T, CRTP<T> > );
}
};
class A {};
int main()
{
CRTP<A> x;
x.Check();
}
What is the assert helping here? It is only a check that you wrote 4 lines above "class CRTP: public T". For me that makes no sense.
I still have no real idea what you want to achieve more than simply using CRTP.

C++ Verify template type

Sorry for my poor english I'll try to do my best.
I want to design an interface that should be used like this:
class MyObject : public IMyInterface<MyObject>
{
// ...
};
The interface could look like this:
template <class _TMyObject>
class IMyInterface
{
virtual _TMyObject* Get() = 0;
};
What i'm looking after, is a way to verify, at compile time, that the interface is used as intended.
How can I test if _TMyObject "is-a" IMyInterface<_TMyObject>? Inside the interface definition, with a static_assert for example.
Thanks for any help :).
Have a nice day!
You can't put static_assert inside the class itself, because D is an incomplete type, but you can put it in the destructor (or constructor, but there can be many constructors):
template<class D>
struct B
{
~B()
{
static_assert(std::is_base_of_v<B, D>);
};
};
struct Not_E {};
struct D : B<D> { };
struct E : B<Not_E> { };
void foo()
{
D d; // OK
E e; // Fails
}
Addition. Note that this solution is not a complete protection against incorrect usage of CRTP. Please refer to Some Programmer Dude's answer for a nice example of error that can't be caught by it.
Since C++11 there are many type property traits that could be used to do checks at compile-time.
For example std::is_base_of which in your case could be used like perhaps
template<typename TChild>
struct IMyInterface
{
static_assert(std::is_base_of<IMyInterface, TChild>::value, "Derived class not derived from IMyInterface");
// ...
};
Note: The exact code shown above will not work directly, but rather show the principle.
Of course, that do allow something like
class MyFirstClass : public IMyInterface<MyFirstClass>
{
// ...
};
// Note wrong class in template
// vvvvvvvvvvvv
class MySecondClass : public IMyInterface<MyFirstClass>
{
// ...
};
So to answer your question if it's possible for such a check: Not really the way you want. Even using other traits and meta-programming, you can never guarantee that the template argument for the interface class is "correct" when used in the CRTP.
The only way I can see it work is by using down-casting at run-time with dynamic_cast, something like dynamic_cast<TChild*>(this) != nullptr in the interface class.

Is such a downcast safe?

Suppose we have the following code:
#include <memory>
#include <vector>
struct BaseComponent
{
template <typename T>
T * as()
{
return static_cast<T*>(this);
}
virtual ~BaseComponent() {}
};
template <typename T>
struct Component : public BaseComponent
{
virtual ~Component() {}
};
struct PositionComponent : public Component<PositionComponent>
{
float x, y, z;
virtual ~PositionComponent() {}
};
int main()
{
std::vector<std::unique_ptr<BaseComponent>> mComponents;
mComponents.emplace_back(new PositionComponent);
auto *pos = mComponents[0]->as<PositionComponent>();
pos->x = 1337;
return 0;
}
In the T * as() method, should I use a static_cast or a dynamic_cast? are there times when the the conversion will fail? Do I need to dynamic_cast like this instead?
auto *ptr = dynamic_cast<T*>(this);
if(ptr == nullptr)
throw std::runtime_error("D'oh!");
return ptr;
In your case there is no way to tell statically whether this is the right type or not.
What you may want is a CRTP (Curiously recurring template pattern):
template <class T>
struct BaseComponent
{
T* as()
{
return static_cast<T*>(this);
}
virtual ~BaseComponent() {}
};
template <typename T>
struct Component : public BaseComponent<T>
{
virtual ~Component() {}
};
struct PositionComponent : public Component<PositionComponent>
{
float x, y, z;
virtual ~PositionComponent() {}
};
This way you can do:
auto x = yourBaseComponent.as();
and have the right child type statically.
The code that you present is correct and well formed, but the cast in general is not safe. If the actual object was not a PositionComponent, then the compiler would very gladly assume that it is and you would be causing undefined behavior.
If you replace the cast with dynamic_cast, then the compiler will generate code that at runtime verifies that the conversion is valid.
The real question is why would you need this. There are reasons, but more often than not the use of casts are an indication of issues with your design. Reconsider whether you can do better (i.e. redesign your code so that you don't need to go explicitly converting types)
Since you are using unique_ptr<BaseComponent>, naturally there could be times when the conversion fails: the insertion of new data in the vector and consumption of that data are done in unrelated places, and in such a way that the compiler cannot enforce it.
Here is an example of an invalid cast:
struct AnotherComponent : public Component<AnotherComponent>
{
virtual ~AnotherComponent () {}
};
std::vector<std::unique_ptr<BaseComponent>> mComponents;
mComponents.emplace_back(new AnotherComponent);
// !!! This code compiles, but it is fundamentally broken !!!
auto *pos = mComponents[0]->as<PositionComponent>();
pos->x = 1337;
In this respect, using dynamic_cast would provide better protection against incorrect usage of the as<T> function. Note that the incorrect usage may not be intentional: any time the compiler cannot check the type for you, and you have a potential type mismatch, you should prefer dynamic_cast<T>
Here is a small demo to illustrate how dynamic_cast would offer you a degree of protection.
You should always use dynamic_cast when casting polymorphic objects that are derived from a baseclass.
In a case where mComponents[0] is not PositionComponent (or a class derived therefrom), the above code would fail. Since the whole purpose of having mComponents hold a pointer to BaseComponent is so that you can put other things than PositionComponent objects into the vector, I'd say you need to care for that particular scenario.
In general, it's a "bad smell" when you are using dynamic_cast (or generally casting objects that are derived from a common baseclass). Typically it means the objects should not be held in a common container, because they are not closely enough related.

Boost lambda with shared_ptr

If I have a polymorphic base class called Base as well as classes Derived1 and Derived2 which inherit from Base. I can then use boost::lambda to create a factory of sorts. Something like:
typedef boost::function<Base *()> Creator;
std::map<std::string,Creator> map1;
map1["Derived1"] = boost::lambda::new_ptr<Derived1>();
map1["Derived2"] = boost::lambda::new_ptr<Derived2>();
(This isn't real code, I'm just trying to illustrate the problem.)
This works, so I can then do a lookup in the map using a string and then invoke the lambda function to instantiate that class. All good.
The problem with this is that it's dealing in raw pointers, I'd prefer to be using smart pointers (std::shared_ptr).
So if I change from:
typedef boost::function<Base *>() Creator;
to:
typedef boost::function<std::shared_ptr<Base> >() Creator;
Then I'm getting stuck from here. I've tried using boost::lambda::bind in conjunction with boost::lambda::new_ptr but I'm not having much luck, can't get past compilation errors. (Huge reams of template-related error output.)
I've checked other similar messages within StackOverflow, Using boost::bind and boost::lambda::new_ptr to return a shared_ptr constructor is close but if I try to apply its solution I get the template errors mentioned above.
I'm happy to provide sample code and the actual errors if it helps, but hopefully the above info is sufficient. I'm using boost 1.47.0 on GCC 4.6 as well as 4.7 snapshot on Fedora 15.
class Base {
public:
virtual ~Base() = 0;
};
Base::~Base() {}
class Derived1 : public Base {};
class Derived2 : public Base {};
typedef boost::shared_ptr<Base> BasePtr;
typedef boost::function<BasePtr()> Creator;
template <typename T>
Creator MakeFactory()
{
namespace la = boost::lambda;
return la::bind(
la::constructor<BasePtr>(),
la::bind(la::new_ptr<T>()));
}
int _tmain(int argc, _TCHAR* argv[])
{
std::map<std::string,Creator> map1;
map1["Derived1"] = MakeFactory<Derived1>();
map1["Derived2"] = MakeFactory<Derived2>();
BasePtr p1 = map1["Derived1"]();
BasePtr p2 = map1["Derived2"]();
return 0;
}
however, why go to the trouble when you could write:
template <typename T>
BasePtr MakeFactoryImpl()
{
return BasePtr(new T());
}
template <typename T>
Creator MakeFactory()
{
return Creator(&MakeFactoryImpl<T>);
}
This is a common problem. The fact that two types are related (in your case by inheritance) does not imply that the instantiations of a template with those two types maintains the same relationship.
The solution is to return always shared_ptr<Base>, since it can hold both pointers to Base or any derived type, which will be semantically compatible with your current version (i.e. in both versions the caller gets a (smart)-pointer-to Base.
As an aside, I would avoid returning shared_ptr from a factory, as you are forcing your choice of smart pointer into all of your users. I would prefer to either return a raw pointer (the user can choose, but it is dangerous in some situations) or a unique_ptr or even auto_ptr, which are safe and still allow the user to choose a different mechanism (i.e. if your function returns an auto_ptr, the user can still use a shared_ptr by doing shared_ptr<Base> p( f().release() );, while the opposite is not possible (memory managed by a shared_ptr cannot be released to use in a different smart pointer.
This quick-and-dirty return type adapter is good not only for converting return types from Derived* to Base*, but between any convertible types. For simplicity, the function-object takes no arguments. With C++11 variadic templates it should be easy to add arbitrary argument handling. Feel free to improve on this in any way you wish.
template <typename ToType>
class return_type_adapter
{
template <typename toType>
class return_type_adapter_impl_base
{
public:
virtual toType call() = 0;
};
template <typename toType, typename Func>
class return_type_adapter_impl : public return_type_adapter_impl_base<toType>
{
public:
return_type_adapter_impl (Func func) : func(func) {}
toType call() { return toType(func()); }
private:
Func func;
};
boost::shared_ptr<return_type_adapter_impl_base<ToType> > impl_base;
public:
ToType operator() () { return impl_base->call(); }
template <typename Func>
return_type_adapter (Func func) :
impl_base(new return_type_adapter_impl<ToType, Func>(func)) {}
};
map1["Derived1"] = boost::lambda::bind(
boost::lambda::constructor<boost::shared_ptr<Base>>(),
boost::lambda::bind(
boost::lambda::new_ptr<Derived1>()));
map1["Derived2"] = boost::lambda::bind(
boost::lambda::constructor<boost::shared_ptr<Base>>(),
boost::lambda::bind(
boost::lambda::new_ptr<Derived2>()));
But honestly, this is the level of complexity where it doesn't really make sense to use boost lambda any more. A simpler solution:
template<typename DerivedType>
boost::shared_ptr<Base> makeDerived() {
return boost::shared_ptr<Base>(new DerivedType);
}
[...]
map1["Derived1"] = makeDerived<Derived1>;
map1["Derived2"] = makeDerived<Derived2>;

Using an abstract deleter with std::unique_ptr

I want to have a run-time interface that offers some creation methods. These methods return unique_ptr<T>, and I want to enable custom deletion by the creating class. The thing is that I definitely don't want the interface to offer these methods directly- they should only be available in the destruction of the unique_ptr<T, SomeCustomDel>. Now, I figured that I can use std::unique_ptr<T, std::function<void(T*)>>, but I'd really rather not because I simply don't need that level of abstraction and I don't want to have to pay the heap allocation.
Any suggestions?
Your specification isn't completely clear to me, but have you considered unique_ptr<T, void(*)(void*)>? This is a very flexible type with many qualities of a dynamic deleter.
If that isn't what you're looking for, you might try something along the lines of:
class impl
{
public:
virtual ~impl();
virtual void operator()(void*) = 0;
virtual void other_functionality() = 0;
};
class my_deleter
{
impl* p_;
public:
...
void operator()(void* p) {(*p_)(p);}
void other_functionality() {p_->other_functionality();}
...
};
It is difficult to know what is best in your case without more details about your requirements.
I wish there was a standard "dynamic" deleter version of std::unique_ptr. This mythical class would allow me to attach a deleter to the unique_ptr when I instantiate it, similar to std::shared_ptr.
That said if such a type existed I suspect it would essentially be implemented with std::unique_ptr<T,std::function<void(T*)>>. The very thing you wanted to avoid.
However I think you're underestimating std::function. Its implementation is optimization to avoid hitting the heap if possible. If your deleter object remains small everything will be done on the stack (I think boost::function can statically handle deleters up to 32 bytes in size).
A for the problem of a too general deleter. You have to provide the definition of the deleter. There is no way around that. However you don't have to let the user instantiate the class, which essentially forbids them from using it. To do this make the deleter's constructor(s) require a tag structure that is only defined in the implementation file.
Or possibly the simplest solution. Put the deleter in a detail namespace. The user is still free to use it, but it's obvious that they should not and can't complain when you change it, breaking their code.
I see two options.
Option 1: Use a custom deleter that contains a function pointer and optionally a raw char array to encode some state if necessary:
template<class T>
void simply_delete(T* ptr, const unsigned char*) {
delete ptr;
}
template<class T, int StateSize>
struct my_deleter {
void (*funptr)(T*,const unsigned char*);
array<unsigned char,StateSize> state;
my_deleter() : funptr(&simply_delete<T>) {}
void operator()(T* ptr) const {
funptr(ptr,StateSize>0 ? &state[0] : nullptr);
}
};
template<class T>
using upi = unique_ptr<T,my_deleter<T,sizeof(void*)>>;
Now, you can create different upi<T> objects that store different function pointers and deleter states without the need of mentioning what exactly is happening in its type. But this is almost the same as a function<> deleter which implements the "small function optimization". You can expect a decent standard library implementation to provide a very efficient function<> wrapper for small function objects (like function pointers) that don't require any heap allocations. At least I do. :)
Option 2: Simply use shared_ptr instead of unique_ptr and make use of its built-in type erasure feature with respect to deleters. This will also allow you to support Derived->Base conversions easily. For greatest control over what is allocated where you could use the std::allocate_shared function template.
This is a response to one of the answers, not to the original question. It is an answer instead of a comment simply because of formatting reasons.
I wish there was a standard "dynamic"
deleter version of std::unique_ptr.
This mythical class would allow me to
attach a deleter to the unique_ptr
when I instantiate it, similar to
std::shared_ptr.
Here is a start of an implementation of such a class. It is fairly easy to do. I've used unique_ptr only as an exception safety aid, nothing more. It is not as full-featured as you might like. These extra features are left as an exercise for the reader. :-) What is below establishes unique ownership of the pointer and storage for the custom dynamic deleter. Note that the smart pointer owns a passed-in pointer even if the constructor of the smart pointer throws (this is actually where unique_ptr is most useful in the implementation).
#include <memory>
#include <type_traits>
namespace detail
{
class impl
{
public:
virtual ~impl() {};
};
template <class T, class D>
class erase_type
: public impl
{
T* t_;
D d_;
public:
explicit erase_type(T* t)
noexcept(std::is_nothrow_default_constructible<D>::value)
: t_(t)
{}
erase_type(T* t, const D& d)
noexcept(std::is_nothrow_copy_constructible<D>::value)
: t_(t),
d_(d)
{}
erase_type(T* t, D&& d)
noexcept(std::is_nothrow_move_constructible<D>::value)
: t_(t),
d_(std::move(d))
{}
virtual ~erase_type()
{
if (t_)
d_(t_);
}
erase_type(const erase_type&) = delete;
erase_type& operator=(const erase_type&) = delete;
};
} // detail
template <class T>
class my_pointer
{
T* ptr_;
detail::impl* impl_;
public:
my_pointer() noexcept
: ptr_(nullptr),
impl_(nullptr)
{}
template <class Y>
explicit my_pointer(Y* p)
: ptr_(static_cast<T*>(p)),
impl_(nullptr)
{
std::unique_ptr<Y> hold(p);
impl_ = new detail::erase_type<Y, std::default_delete<Y>>(p);
hold.release();
}
template <class Y, class D>
explicit my_pointer(Y* p, D&& d)
: ptr_(static_cast<T*>(p)),
impl_(nullptr)
{
std::unique_ptr<Y, D&> hold(p, d);
typedef
detail::erase_type<Y, typename std::remove_reference<D>::type>
ErasedType;
impl_ = new ErasedType(p, std::forward<D>(d));
hold.release();
}
~my_pointer()
{
delete impl_;
}
my_pointer(my_pointer&& p) noexcept
: ptr_(p.ptr_),
impl_(p.impl_)
{
p.ptr_ = nullptr;
p.impl_ = nullptr;
}
my_pointer& operator=(my_pointer&& p) noexcept
{
delete impl_;
ptr_ = p.ptr_;
impl_ = p.impl_;
p.ptr_ = nullptr;
p.impl_ = nullptr;
return *this;
}
typename std::add_lvalue_reference<T>::type
operator*() const noexcept
{return *ptr_;}
T* operator->() const noexcept
{return ptr_;}
};
Note that unlike unique_ptr (and like shared_ptr), the constructors taking a pointer are not noexcept. Although that could possibly be mitigated via the use of a "small deleter" optimization. Yet another exercise left for the reader. :-)
I found this question googling my own problem; using unique_ptr with an abstract base class pointer. All the answers are great. I found #deft_code's one to be the best for my needs.
This is what I ended up doing in my case:
Suppose T is an abstract base class type. The makeT(), func creates a new instance of some derived class, and returns the T*:
std::unique_ptr<T, std::function<void(T*)>> p(makeT(), [](T* p){p.delete();});
I just wanted to share this for those who are looking for short, copy and pasteish solution.
For the untrained c++11 eyes, the [](... syntax is a lambda.
As is mentioned in the other answers, it's not a 'function pointer' in the C sense, but a callable c++ object, which is really tiny, and should have negligible overhead to carry it around.