Say you have a function like this :
SmartPtr<A> doSomething(SmartPtr<A> a);
And classes like this :
class A { }
class B : public A { }
And now I do this :
SmartPtr<A> foo = new B();
doSomething(foo);
Now, I would like to get back a SmartPtr<B> object from doSomething.
SmartPtr<B> b = doSomething(foo);
Is it possible ? What kind of casting do I have to do ?
Right now, I just found something I believe ugly :
B* b = (B*)doSomething().get()
Important notes : I do not have any access to SmartPtr and doSomething() code.
Instead of doing that, you can do this :
B *b = dynamic_cast< B* >( doSomething.get() );
but you have to check if b is NULL.
For anyone stumbling across this decade old question while looking for how to do this, C++11 added dynamic_pointer_cast, static_pointer_cast, and const_pointer_cast to do exactly this.
Now this problem is as simple as
shared_ptr<B> b=static_pointer_cast<B>(doSomething(foo));
You can define your own SmartPtrCast template function which does something like:
template <typename DestT, typename SrcT>
inline SmartPtr<DestT> SmartPtrCast(const SmartPtr<SrcT> &src)
{
return SmartPtr<DestT>(static_cast<DestT*>(src.get()));
}
Then, all you have to do cast gracefully from A to B is:
SmartPtr<B> b = SmartPtrCast<B>(doSomething(foo));
Caveat Emptor:
This will only work if the smart pointer returned by doSomething() is referenced somewhere else, and is not destroyed when it goes out of scope. Judging by your example, this is the case, but it's still not as graceful, and it should be noted that the two pointers won't share their reference counting (so if one of them gets destroyed, the second will lose its data).
A better solution is either to detach one of the pointers (if SmartPtr has a detach method). An even better solution (if you don't have a detach method or if you want to share the reference count) is to use a wrapper class:
template <typename SrcT, typename DestT>
class CastedSmartPtr
{
private:
SmartPtr<SrcT> ptr;
public:
CastedSmartPtr(const SmartPtr<SrcT>& src)
{
ptr = src;
}
DestT& operator* () const
{
return *(static_cast<DestT*> >(ptr.get()));
}
DestT* operator->() const
{
return static_cast<DestT*> >(ptr.get());
}
DestT* get() const
{
return static_cast<DestT*> >(ptr.get());
}
}
template <typename DestT, typename SrcT>
inline SmartPtr<DestT> SmartPtrCast(const SmartPtr<SrcT>& src)
{
return CastedSmartPtr<SrcT, DestT>(src);
}
This will use a SmartPtr internally (so reference count is properly shared) and static_cast it to internally to DestT (with no performance impact). If you want to use dynamic_cast, you can do it only once, in the constructor, to avoid unnecessary overhead. You may also want to add additional method to the wrapper such as copy constructor, assignment operator, detach method, etc.
SmartPtr<B> b = dynamic_cast<B*>(doSomething().get())
or perhaps something like doSomething().dynamic_cast<B*>() if your SmartPtr supports it.
Related
If I store a polymorphic functor in an std::function, is there a way to extract the functor without knowing the concrete type?
Here is a simplified version of the code:
struct Base {
//...
virtual int operator()(int foo) const = 0;
void setBar(int bar){}
};
struct Derived : Base {
//...
int operator()(int foo) const override {}
};
std::function<int(int)> getFunction() {
return Derived();
}
int main() {
auto f = getFunction();
// How do I call setBar() ?
if (Base* b = f.target<Base>()) {} // Fails: returns nullptr
else if(Derived* d = f.target<Derived>()) {
d->setBar(5); // Works but requires Derived type
}
std::cout << f(7) << std::endl;
return 0;
}
I want the client to be able to provide their own function, and for my handler to use the functionality of the Base if it's available.
The fall back would be of course to just use the abstract base class instead of std::function and clients would implement the ABC interface as they would have pre-C++11:
std::shared_ptr<Base> getFunction {
return std::make_shared<Derived>();
}
but I wanted to know if it's possible to create a more flexible and easier to use interface with C++14. It seems all that's missing is a cast inside std::function::target
It seems all that's missing is a cast inside std::function::target
All target<T> currently needs is to check target_id<T> == stored_type_info.
Being able to cast back to the real (erased) type in a context where that type may not be visible, and then check how it's related to the requested type ... is not really feasible.
Anyway, std::function is polymorphic only on the function signature. That's the thing it abstracts. If you want general-purpose polymorphism, just return a unique_ptr<Base> and use that.
If you really want function<int(int)> for the function-call syntax, instantiate it with a pimpl wrapper for unique_ptr<Base>.
Possible solution would be to have a thin wrapper:
struct BaseCaller {
BaseCaller( std::unique_ptr<Base> ptr ) : ptr_( std::move( ptr ) ) {}
int operator()( int foo ) { return (*ptr)( foo ); }
std::unique_ptr<Base> ptr_;
};
now user must create all derived from Base classed through this wrapper:
std::function<int(int)> getFunction() {
return BaseCaller( std::make_unique<Derived>() );
}
and you check in your call that target is a BaseCaller.
I want the client to be able to provide their own function, and for my handler to use the functionality of the Base if it's available.
The main drawback to using virtual dispatch is that it may create an optimization barrier. For instance, the virtual function calls cannot usually be inlined, and "devirtualization" optimizations are generally pretty difficult for the compiler to actually do in practical situations.
If you are in a situation where the code is performance critical, you can roll your own type-erasure and avoid any vtable / dynamic allocations.
I'm going to follow a pattern demonstrated in an old (but well-known) article, the "Impossibly Fast Delegates".
// Represents a pointer to a class implementing your interface
class InterfacePtr {
using ObjectPtr = void*;
using CallOperator_t = int(*)(ObjectPtr, int);
using SetBar_t = void(ObjectPtr, int);
ObjectPtr obj_;
CallOperator_t call_;
SetBar_t set_bar_;
// Ctor takes any type that implements your interface,
// stores pointer to it as void * and lambda functions
// that undo the cast and forward the call
template <typename T>
InterfacePtr(T * t)
: obj_(static_cast<ObjectPtr>(t))
, call_(+[](ObjectPtr ptr, int i) { return (*static_cast<T*>(ptr))(i); })
, set_bar_(+[](ObjectPtr ptr, int i) { static_cast<T*>(ptr)->set_bar(i); })
{}
int operator()(int i) {
return call_(obj_, i);
}
void set_bar()(int i) {
return set_bar_(obj_, i);
}
};
Then, you would take InterfacePtr instead of a pointer to Base in your API.
If you want the interface member set_bar to be optional, then you could use SFINAE to detect whether set_bar is present, and have two versions of the constructor, one for when it is, and one for when it isn't. There is recently a really great exposition of the "detection idiom" at various C++ standards on Tartan Llama's blog, here. The advantage of that would be that you get something similar to what virtual gives you, with the possibility to optionally override functions, but the dispatch decisions get made at compile-time, and you aren't forced to have a vtable. And all of the functions can potentially be inlined if the optimizer can prove to itself that e.g. in some compilation unit using this, only one type is actually passed to your API through this mechanism.
A difference is that this InterfacePtr is non-owning and doesn't have the dtor or own the storage of the object it's pointing to.
If you want InterfacePtr to be owning, like std::function, and copy the functor into its own memory and take care of deleting it when it goes out of scope, then I'd recommend to use std::any to represent the object instead of void *, and use std::any_cast in the lambdas instead of static_cast<T*> in my implementation. There's some good further discussion of std::any and why it's good for this usecase on /r/cpp here.
I don't think there's any way to do what you were originally asking, and recover the "original" functor type from std::function. Type erasure erases the type, you can't get it back without doing something squirrelly.
Edit: Another alternative you might consider is to use a type-erasure library like dyno
std::function<X>::target<T> can only cast back to exactly T*.
This is because storing how to convert to every type that can be converted to T* would require storing more information. It takes information to convert a pointer-to-derived to a pointer-to-base in the general case in C++.
target is intended to simply permit replacing some function-pointer style machinery with std::functions and have the existing machinery work, and do so with nearly zero cost (just compare typeids). Extending that cost to every base type of the stored type would have been hard, so it wasn't done, and won't be free, so it probably won't be done in the future.
std::function is, however, just an example of type erasure, and you can roll your own with additional functionality.
The first thing I'd do is I would do away with your virtual operator(). Type-erasure based polymorphism doesn't need that.
The second thing is get your hands on an any -- either boost::any or c++17's std::any.
That writes the hard part of type erasure -- small buffer optimization and value storage -- for you.
Add to that your own dispatch table.
template<class Sig>
struct my_extended_function;
template<class R, class...Args>
struct my_extended_function<R(Args...)> {
struct vtable {
R(*f)(any&, Args&&...) = 0;
void*(*cast)(any&, std::type_info const&) = 0;
};
template<class...Bases, class T>
my_extended_function make_with_bases( T t ) {
return {
get_vtable<T, Bases...>(),
std::move(t)
};
}
R operator()(Args...args)const {
return (*p_vtable->f)(state, std::forward<Args>(args)...);
}
private:
template<class T, class...Bases>
static vtable make_vtable() {
vtable ret{
// TODO: R=void needs different version
+[](any& ptr, Args&&...args)->R {
return (*any_cast<T*>(ptr))(std::forward<Args>(args)...);
},
+[](any& ptr, std::type_info const& tid)->void* {
T* pt = any_cast<T*>(ptr);
if (typeid(pt)==tid) return pt;
// TODO: iterate over Bases, see if any match tid
// implicitly cast pt to the Bases* in question, and return it.
}
};
}
template<class T, class...Bases>
vtable const* get_vtable() {
static vtable const r = make_vtable<T,Bases...>();
return &r;
}
vtable const* p_vtable = nullptr;
mutable std::any state;
my_extended_function( vtable const* vt, std::any s ):
p_vtable(vt),
state(std::move(s))
{}
};
As you know it is not possible to use the std::enable_shared_from_this and shared_from_this() pair from the constructor of an object since a shared_pointer containing the class is not yet in existance. However, I really would like this functionality. I have attempted my own system and it seems to be working OK.
namespace kp
{
template <class T>
void construct_deleter(T *t)
{
if(!t->_construct_pself)
{
t->~T();
}
free(t);
}
template <class T, typename... Params>
std::shared_ptr<T> make_shared(Params&&... args)
{
std::shared_ptr<T> rtn;
T *t = (T *)calloc(1, sizeof(T));
t->_construct_pself = &rtn;
rtn.reset(t, construct_deleter<T>);
t = new(t) T(std::forward<Params>(args)...);
t->_construct_pself = NULL;
t->_construct_self = rtn;
return rtn;
}
template <class T>
class enable_shared_from_this
{
public:
std::shared_ptr<T> *_construct_pself;
std::weak_ptr<T> _construct_self;
std::shared_ptr<T> shared_from_this()
{
if(_construct_pself)
{
return *_construct_pself;
}
else
{
return _construct_self.lock();
}
}
};
}
Can anyone spot any flaws in this logic? I basically use placement new to assign a pointer to the shared_ptr inside the class before the constructor calls.
As it stands I can use it as so:
std::shared_ptr<Employee> emp = kp::make_shared<Employee>("Karsten", 30);
and in the Employee constructor:
Employee::Employee(std::string name, int age)
{
Dept::addEmployee(shared_from_this());
}
Before I commit this to a relatively large codebase, I would really appreciate some ideas or feedback from you guys.
Thanks!
I know it's been a while but that might be useful to someone with the same issue : the main problem will happen if you attempt to inherit from a class inheriting your enable_shared_from_this.
Especially with this line :
t->_construct_pself = &rtn;
If you have let's say :
class Object : public kp::enable_shared_from_this<Object> {
};
class Component : public Object {
};
Then the compiler won't be able to cast std::shared_ptr<Component>* to std::shared_ptr<Object>* as for the compiler those types are not related even though Component inherits Object.
The easiest solution I see would be to turn _construct_pself to void* like so :
template <class T>
class enable_shared_from_this
{
public:
void* _construct_pself{ nullptr };
std::weak_ptr<T> _construct_self;
std::shared_ptr<T> shared_from_this() const
{
if (_construct_pself)
{
return *static_cast<std::shared_ptr<T>*>(_construct_pself);
}
else
{
return _construct_self.lock();
}
}
};
And then do
t->_construct_pself = static_cast<void*>(&rtn);
It's not very sexy and might make other issues arise but it seems to be working...
[EDIT] There is a slightly better and more "C++" alternative, sorry for not thinking about it right away, just do :
t->_construct_pself = reinterpret_cast<decltype(t->_construct_pself)>(&rtn);
[EDIT2] Make shared_from_this const as it does not change anything in the class
[EDIT3] Found an other issue : If you use a copy constructor via make_shared and use operator= inside the constructor before shared_from_this, shared_from_this will return the address of copied object, not of the object's copy. Only solution I see is to define empty copy constructor and assignment operator for enable_shared_from_this and explicitly call the copy constructor from inheriting classes everytime needed... Either that or MAKE SURE you NEVER call operator= before shared_from_this inside your copy constructor.
I think there is a semantically problem with using shared_from_this() inside the constructor.
The issue is when an exception is being thrown there is no valid object, but you already have setup a shared pointer to it. e.g.:
Employee::Employee(std::string name, int age)
{
Dept::addEmployee(shared_from_this());
if (...) throw std::runtime_error("...");
}
Now Dept will have a pointer to this object, which wasn't successfully created.
Use of shared_from_this() in a constructor should be a code smell, even if it worked, because it is a sign of a possible circular dependency and/or use of a pointer to an incomplete object.
One typically calls shared_from_this() to pass a smart pointer to this object to another object. Doing this during construction would mean that "this" class depends on another component, which depends on "this" class.
Even in the (arguably) valid use case of an object self-registering at some other component, one would be registering an object that is not yet fully constructed, which is a recipe for problems, as pointed out, for example, in this answer.
The solution I would recommend is therefore to analyze the code or design and look for possible circular dependencies, then break that cycle.
In the "self-registering object" use case, consider moving the responsibility of registration somewhere else, for example, to the same place where the object is being instantiated. If necessary, use a "create" function or factory rather than direct construction.
So, I have something along the lines of these structs:
struct Generic {}
struct Specific : Generic {}
At some point I have the the need to downcast, ie:
Specific s = (Specific) GetGenericData();
This is a problem because I get error messages stating that no user-defined cast was available.
I can change the code to be:
Specific s = (*(Specific *)&GetGenericData())
or using reinterpret_cast, it would be:
Specific s = *reinterpret_cast<Specific *>(&GetGenericData());
But, is there a way to make this cleaner? Perhaps using a macro or template?
I looked at this post C++ covariant templates, and I think it has some similarities, but not sure how to rewrite it for my case. I really don't want to define things as SmartPtr. I would rather keep things as the objects they are.
It looks like GetGenericData() from your usage returns a Generic by-value, in which case a cast to Specific will be unsafe due to object slicing.
To do what you want to do, you should make it return a pointer or reference:
Generic* GetGenericData();
Generic& GetGenericDataRef();
And then you can perform a cast:
// safe, returns nullptr if it's not actually a Specific*
auto safe = dynamic_cast<Specific*>(GetGenericData());
// for references, this will throw std::bad_cast
// if you try the wrong type
auto& safe_ref = dynamic_cast<Specific&>(GetGenericDataRef());
// unsafe, undefined behavior if it's the wrong type,
// but faster if it is
auto unsafe = static_cast<Specific*>(GetGenericData());
I assume here that your data is simple.
struct Generic {
int x=0;
int y=0;
};
struct Specific:Generic{
int z=0;
explicit Specific(Generic const&o):Generic(o){}
// boilerplate, some may not be needed, but good habit:
Specific()=default;
Specific(Specific const&)=default;
Specific(Specific &&)=default;
Specific& operator=(Specific const&)=default;
Specific& operator=(Specific &&)=default;
};
and bob is your uncle. It is somewhat important that int z hae a default initializer, so we don't have to repeat it in the from-parent ctor.
I made thr ctor explicit so it will be called only explicitly, instead of by accident.
This is a suitable solution for simple data.
So the first step is to realize you have a dynamic state problem. The nature of the state you store changes based off dynamic information.
struct GenericState { virtual ~GenericState() {} }; // data in here
struct Generic;
template<class D>
struct GenericBase {
D& self() { return *static_cast<D&>(*this); }
D const& self() const { return *static_cast<D&>(*this); }
// code to interact with GenericState here via self().pImpl
// if you have `virtual` behavior, have a non-virtual method forward to
// a `virtual` method in GenericState.
};
struct Generic:GenericBase<Generic> {
// ctors go here, creates a GenericState in the pImpl below, or whatever
~GenericState() {} // not virtual
private:
friend struct GenericBase<Generic>;
std::unique_ptr<GenericState> pImpl;
};
struct SpecificState : GenericState {
// specific stuff in here, including possible virtual method overrides
};
struct Specific : GenericBase<Specific> {
// different ctors, creates a SpecificState in a pImpl
// upcast operators:
operator Generic() && { /* move pImpl into return value */ }
operator Generic() const& { /* copy pImpl into return value */ }
private:
friend struct GenericBase<Specific>;
std::unique_ptr<SpecificState> pImpl;
};
If you want the ability to copy, implement a virtual GenericState* clone() const method in GenericState, and in SpecificState override it covariantly.
What I have done here is regularized the type (or semiregularized if we don't support move). The Specific and Generic types are unrelated, but their back end implementation details (GenericState and SpecificState) are related.
Interface duplication is avoided mostly via CRTP and GenericBase.
Downcasting now can either involve a dynamic check or not. You go through the pImpl and cast it over. If done in an rvalue context, it moves -- if in an lvalue context, it copies.
You could use shared pointers instead of unique pointers if you prefer. That would permit non-copy non-move based casting.
Ok, after some additional study, I am wondering if what is wrong with doing this:
struct Generic {}
struct Specific : Generic {
Specific( const Generic &obj ) : Generic(obj) {}
}
Correct me if I am wrong, but this works using the implicit copy constructors.
Assuming that is the case, I can avoid having to write one and does perform the casting automatically, and I can now write:
Specific s = GetGenericData();
Granted, for large objects, this is probably not a good idea, but for smaller ones, will this be a "correct" solution?
I'm currently investigating the interplay between polymorphic types and assignment operations. My main concern is whether or not someone might try assigning the value of a base class to an object of a derived class, which would cause problems.
From this answer I learned that the assignment operator of the base class is always hidden by the implicitely defined assignment operator of the derived class. So for assignment to a simple variable, incorrect types will cause compiler errors. However, this is not true if the assignment occurs via a reference:
class A { public: int a; };
class B : public A { public: int b; };
int main() {
A a; a.a = 1;
B b; b.a = 2; b.b = 3;
// b = a; // good: won't compile
A& c = b;
c = a; // bad: inconcistent assignment
return b.a*10 + b.b; // returns 13
}
This form of assignment would likely lead to inconcistent object state, however there is no compiler warning and the code looks non-evil to me at first glance.
Is there any established idiom to detect such issues?
I guess I only can hope for run-time detection, throwing an exception if I find such an invalid assignment. The best approach I can think of just now is a user-defined assigment operator in the base class, which uses run-time type information to ensure that this is actually a pointer to an instance of base, not to a derived class, and then does a manual member-by-member copy. This sounds like a lot of overhead, and severely impact code readability. Is there something easier?
Edit: Since the applicability of some approaches seems to depend on what I want to do, here are some details.
I have two mathematical concepts, say ring and field. Every field is a ring, but not conversely. There are several implementations for each, and they share common base classes, namely AbstractRing and AbstractField, the latter derived from the former. Now I try to implement easy-to-write by-reference semantics based on std::shared_ptr. So my Ring class contains a std::shared_ptr<AbstractRing> holding its implementation, and a bunch of methods forwarding to that. I'd like to write Field as inheriting from Ring so I don't have to repeat those methods. The methods specific to a field would simply cast the pointer to AbstractField, and I'd like to do that cast statically. I can ensure that the pointer is actually an AbstractField at construction, but I'm worried that someone will assign a Ring to a Ring& which is actually a Field, thus breaking my assumed invariant about the contained shared pointer.
Since the assignment to a downcast type reference can't be detected at compile time I would suggest a dynamic solution. It's an unusual case and I'd usually be against this, but using a virtual assignment operator might be required.
class Ring {
virtual Ring& operator = ( const Ring& ring ) {
/* Do ring assignment stuff. */
return *this;
}
};
class Field {
virtual Ring& operator = ( const Ring& ring ) {
/* Trying to assign a Ring to a Field. */
throw someTypeError();
}
virtual Field& operator = ( const Field& field ) {
/* Allow assignment of complete fields. */
return *this;
}
};
This is probably the most sensible approach.
An alternative may be to create a template class for references that can keep track of this and simply forbid the usage of basic pointers * and references &. A templated solution may be trickier to implement correctly but would allow static typechecking that forbids the downcast. Here's a basic version that at least for me correctly gives a compilation error with "noDerivs( b )" being the origin of the error, using GCC 4.8 and the -std=c++11 flag (for static_assert).
#include <type_traits>
template<class T>
struct CompleteRef {
T& ref;
template<class S>
CompleteRef( S& ref ) : ref( ref ) {
static_assert( std::is_same<T,S>::value, "Downcasting not allowed" );
}
T& get() const { return ref; }
};
class A { int a; };
class B : public A { int b; };
void noDerivs( CompleteRef<A> a_ref ) {
A& a = a_ref.get();
}
int main() {
A a;
B b;
noDerivs( a );
noDerivs( b );
return 0;
}
This specific template can still be fooled if the user first creates a reference of his own and passes that as an argument. In the end, guarding your users from doing stupid things is an hopeless endeavor. Sometimes all you can do is give a fair warning and present a detailed best-practice documentation.
I will keep it short and just show you a code example:
class myClass
{
public:
myClass();
int a;
int b;
int c;
}
// In the myClass.cpp or whatever
myClass::myClass( )
{
a = 0;
b = 0;
c = 0;
}
Okay. If I know have an instance of myClass and set some random garbage to a, b and c.
What is the best way to reset them all to the state after the class constructor was called, so: 0, 0 and 0?
I came up with this way:
myClass emptyInstance;
myUsedInstance = emptyInstance; // Ewww.. code smell?
Or..
myUsedInstance.a = 0; myUsedInstance.c = 0; myUsedInstance.c = 0;
I think you know what I want, is there any better way to achieve this?
myUsedInstance = myClass();
C++11 is very efficient if you use this form; the move assignment operator will take care of manually cleaning each member.
You can implement clear as a generic function for any swappable type. (A type being swappable is common and done implicitly in C++0x with a move constructor. If you have a copy constructor and assignment operator that behave appropriately, then your type is automatically swappable in current C++. You can customize swapping for your types easily, too.)
template<class C>
C& clear(C& container) {
C empty;
using std::swap;
swap(empty, container);
return container;
}
This requires the least work from you, even though it may appear slightly more complicated, because it only has to be done once and then works just about everywhere. It uses the empty-swap idiom to account for classes (such as std::vector) which don't clear everything on assignment.
If you have seen that the swap is a performance bottleneck (which would be rare), specialize it (without having to change any use of clear!) in myClass's header:
template<>
myClass& clear<myClass>(myClass& container) {
container = myClass();
return container;
}
If myClass is a template, you cannot partially specialize clear, but you can overload it (again in the class header):
template<class T>
myClass<T>& clear(myClass<T>& container) {
container = myClass<T>();
return container;
}
The reason to define such specialization or overload in myClass's header is to make it easy to avoid violating the ODR by having them available in one place and not in another. (I.e. they are always available if myClass is available.)
Just assign to a default-constructed class, like you have. Just use a temporary, though:
struct foo
{
int a, b, c;
foo() :
a(), b(), c()
{} // use initializer lists
};
foo f;
f.a = f.b =f.c = 1;
f = foo(); // reset
You may want to consider using placement new. This will allow you to use the same memory but call the constructor again.
Don't forget to call the destructor before using placement new, however.
Well, there is a much much more elegant way:
Create a vector of your classes with single element and update that element calling the
constructor:
std::vector<your_class> YourClasses;
YourClasses.resize(1);
YourClasses[0] = YourClass(...);
YourClass &y_c = *(&YourClasses[0]);
// do whatever you do with y_c
// and then if you want to re-initialize, do this
YourClasses[0] = YourClass(...);
// and voilla, continue working with resetted y_c