I have an object (Z) which derives from two other objects (A and B).
A and B both derive from enable_shared_from_this<>, respectively enable_shared_from_this<A> and enable_shared_from_this<B>.
Of course I call shared_from_this() on Z. And of course the compiler reports this as ambiguous.
My questions are :
is it safe to inherit twice from enable_shared_from_this<> or will it create two separated reference counts (bad !)
If not safe, how do I solve this ?
Note :
I've found this other question bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this but it doesn't really answer. Should I use the virtual trick too ?
Yes, as per bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this the solution is to use virtual inheritance. Here's an implementation for the C++11 standard shared_ptr (not Boost):
#include <memory>
struct virtual_enable_shared_from_this_base:
std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
virtual ~virtual_enable_shared_from_this_base() {}
};
template<typename T>
struct virtual_enable_shared_from_this:
virtual virtual_enable_shared_from_this_base {
std::shared_ptr<T> shared_from_this() {
return std::dynamic_pointer_cast<T>(
virtual_enable_shared_from_this_base::shared_from_this());
}
};
struct A: virtual_enable_shared_from_this<A> {};
struct B: virtual_enable_shared_from_this<B> {};
struct Z: A, B { };
int main() {
std::shared_ptr<Z> z = std::make_shared<Z>();
std::shared_ptr<B> b = z->B::shared_from_this();
}
This isn't part of the default implementation, probably because of the overhead of virtual inheritance.
Yep, your class will be derived from two distinct classes enable_shared_from_this<A> and enable_shared_from_this<B>, and have two different weak ref's
Trick from that answer allows to have one base class, because of virtual inheritance
Using the shared_ptr aliasing constructor, a variation of ecatmur's answer can be derived:
#include <memory>
struct virtual_enable_shared_from_this_base:
std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
virtual ~virtual_enable_shared_from_this_base() {}
};
template<typename T>
struct virtual_enable_shared_from_this:
virtual virtual_enable_shared_from_this_base {
std::shared_ptr<T> shared_from_this() {
return std::shared_ptr<T>(
virtual_enable_shared_from_this_base::shared_from_this(),
static_cast<T*>(this));
}
std::shared_ptr<const T> shared_from_this() const {
return std::shared_ptr<const T>(
virtual_enable_shared_from_this_base::shared_from_this(),
static_cast<const T*>(this));
}
};
struct A: virtual_enable_shared_from_this<A> {};
struct B: virtual_enable_shared_from_this<B> {};
struct Z: A, B { };
int main() {
std::shared_ptr<Z> z = std::make_shared<Z>();
std::shared_ptr<B> b = z->B::shared_from_this();
}
I expect this version to be faster in many circumstances, since it avoids a costly dynamic cast. However, as usual, only benchmarks have the final word. Also, I have added the const variation.
Related
I am wondering about a short code example of an application of downcast via static_cast, under conditions where there is no undefined behaviour.
I have looked around and I found quite a few texts (posts, Q&A, etc.) referring to fragments of the standard, explaining, etc.
But I found no examples that illustrate that (and that surprises me).
Could anyone provide one such example?
A downcast via static_cast is part of the typical implementation of the Curiously recurring template pattern (CRTP). The example from wikipedia:
template <class T>
struct Base
{
void interface()
{
// ...
static_cast<T*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
T::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Base "knows" that it can downcast this to T* via static_cast (rather than dynamic_cast) because the whole purpose of Base is to be inherited by T. For more details on CRTP I refer you to the wikipedia article.
A very basic example:
class Animal {};
class Dog : public Animal {};
void doSomething() {
Animal *a = new Dog();
Dog *d = static_cast<Dog*>(a);
}
A more contrived example:
class A { public: int a; };
class B : public A {};
class C : public A {};
class D : public B, public C {};
void doSomething() {
D *d = new D();
int bValue = static_cast<B*>(d)->a;
int cValue = static_cast<C*>(d)->a;
// This does not work because we have two a members in D!
// int eitherValue = d->a;
}
There are also countless other cases where you know the actual type type of the instance due to some flags or invariants in your program. However, many sources recommend preferring dynamic_cast in all cases to avoid errors.
I run into a trouble with templates and inheritance. Consider following code:
#include <iostream>
using namespace std;
class TemplateBase {
public:
TemplateBase() {}
};
class TemplateA: public TemplateBase {
public:
TemplateA():TemplateBase() {}
};
template <class T>
class Base {
public:
Base() {}
};
class Derived: public Base<TemplateA> {
public:
Derived(): Base() {}
};
int main()
{
Base<TemplateBase>* a = new Base<TemplateBase>(); // ok
Base<TemplateA>* b = new Derived(); // ok
Base<TemplateBase>* c = new Derived(); // error: cannot convert ‘Derived*’ to ‘Base<TemplateBase>*’ in initialization
}
The problem is the assignment of pointer c, which fails from unknown reason for me. I am trying to assign the Derived<AnotherDerived> to Base<AnotherBase>, is this possible?
Thank you for any help.
Your Derived is a non-template class derived from Base<TemplateA>. In the line
Base<TemplateBase>* c = new Derived();
you are trying to refer to a Derived object via a pointer to Base<TemplateBase>. For the compiler, there is no relation between Base<TemplateBase> and Derived, hence it fails. The only possible base to use is Base<TemplateA> from which Derived is derived.
A possible solution is to templatize the Derived, like
template<typename T>
class Derived: public Base<T> {
public:
Derived(): Base<T>() {}
};
then use as
Base<TemplateBase>* c = new Derived<TemplateBase>;
See a live example here.
vsoftco gives a good outline of why this is invalid. An example of why this is the case in C++ is that although TemplateBase and TemplateA are related, Base<TemplateBase> and Base<TemplateA> are completely different. We could even specialize Base in a way which makes them have an incompatible interface:
template<>
struct Base<TemplateBase>
{
Base() = delete;
Base(int i) {}
}
Now it's obvious that Base<TemplateBase> and Base<TemplateA> can't be used in the same way, because one is default-constructable and one isn't. As such, it's impossible to use them polymorphically, because the compiler won't know what code to generate.
Polymorphism says a base class pointer can point to a derived class object.
But the same can't happen for templates.
Since Polymorphism is a dynamic feature and bound at run-time.
Templates are a static feature and bound at the compile time.
You make a common mistake, you think that relation between classes:
class A {};
class B : public A {};
Will propagate this relation to templates:
template <class T>
class Tmpl {};
Tmpl<A> a; Tmpl<B> b;
a = b; // fails!
So you expected that Tmpl<A> would be a parent to Tmpl<B> but that is not the case. To simulate that you would need to make a constructor, that allows such conversion:
template <class T>
class Tmpl {
T data;
public:
Tmpl() : data() {}
template<class Parent>
Tmpl( const Tmpl<Parent> &t ) : data( t.data ) {}
};
Tmpl<A> a; Tmpl<B> b;
a = b; // works!
For details you should look into smart pointer implementation, there is similar problem there - assignment from pointer to child from base needs to work.
The Derived class is derived from Base<TemplateA> so Base<TemplateBase>* c = new Derived() is equivalent to saying
Base<TemplateBase>* c = new Base<TemplateA>() which is incorrect because Base<TemplateA> is a different class altogether.
TemplateBase is a base class for TemplateA but same does not hold true for Base<TemplateBase> and Base<TemplateA>.
Is there a way to downcast from a virtual base class to a derived class when there are no virtual functions involved? Here's some code to demonstrate what I'm talking about:
struct Base1
{
int data;
};
struct Base2
{
char odd_size[9];
};
struct ViBase
{
double value;
};
struct MostDerived : Base1, Base2, virtual ViBase
{
bool ok;
};
void foo(ViBase &v)
{
MostDerived &md = somehow_cast<MostDerived&>(v); //but HOW?
md.ok = true;
}
int main()
{
MostDerived md;
foo(md);
}
Please note that the code is for demonstration only. My real scenario is fairly complex and involves template parameters and casting from one to another, knowing only that the first one is a base of the second one; it can be a normal or virtual base and it may or may not have virtual functions. (See simplified example at the bottom). I can detect the polymorphic case and the virtual/non-virtual base case using type traits, and solve all of them except the non-polymorphic virtual base. So that's what I'm asking about.
I can't really think of a way to do the cast:
Implicit conversions are right out; these only do upcasts.
static_cast is explicitly forbidden for casting from a virtual base class:
5.2.9/2 ... and B is neither a virtual base class of D nor a base class of a virtual base class of D. ...
dynamic_cast can't do it either, as downcasts require a polymorphic class
5.2.7/6 Otherwise, v shall be a pointer to or a glvalue of a polymorphic type (10.3).
10.3/1 ... A class that declares or inherits a virtual function is called a polymorphic class.
reinterpret_cast doesn't apply here at all.
If MostDerived had at least one virtual function, this could of course be solved with dynamic_cast. But when it does not, is there a way to do the cast?
(NOTE All quotes are taken from C++11 draft N3485)
In light of comments focusing on the above example code too much, here's a sketch of what my real situation is:
template <class T_MostDerived>
struct Bar
{
template <class T_Base>
void foo(T_Base &b, typename std::enable_if<std::is_base_of<T_Base, T_MostDerived>::value>::type * = nullptr)
{
T_MostDerived &md = somehow_cast<T_MostDerived>(b);
do_stuff_with(md);
}
};
That is, I know that T_Base is a base class of T_MostDerived (and I know that T_MostDerived is really the most derived type), but I don't know anything else about them; Bar is my code, part of a library, which unknown clients can use. I can detect that it's a non-polymorphic virtual base, but I can't cast it in such case.
There is an implicit unambigious conversion from MostDerived& to its ViBase&. A static_cast can express such a conversion explicitly, and can also do the opposite conversion. That’s the kinds of conversions that static_cast does.
As the OP noted a static_cast down from virtual base is invalid.
The source code below illustrates why:
#include <iostream>
using namespace std;
struct B { virtual ~B(){} };
struct D: virtual B {};
struct E: virtual B {};
struct X: D, E {};
auto main() -> int
{
X x;
B& b = static_cast<E&>( x );
// Can't do the following for the address adjustment that would work for
// D sub-object won't work for E sub-object, yet declarations of D and E
// are identical -- so the address adjustment can't be inferred from that.
//
//static_cast<D&>( b );
// This is OK:
dynamic_cast<D&>( b );
}
Essentially, as this shows, you can't infer the address adjustment from the declaration of D (or E) alone. And neither can the compiler. This also rules out reinterpret_cast.
This requires a hack. A downcast requires math since multiple inheritance may put the base class in some arbitrary position within the derived class. However, if you know the base class is virtually inherited, then there should only be one instance of it in the derived class. This means you can create a conversion function:
struct MostDerived : Base1, Base2, virtual ViBase
{
bool ok;
template <typename T> static MostDerived * somehow_cast (T *v) {
static MostDerived derived;
static T &from = derived;
static size_t delta
= reinterpret_cast<char *>(&from) - reinterpret_cast<char *>(&derived);
char *to = reinterpret_cast<char *>(v);
return reinterpret_cast<MostDerived *>(to - delta);
}
};
What the special C++ casts give you that this function does not is type safety. This function blindly assumes that the passed in ViBase has an appropriate derived child to cast into, which is generally not the case.
I am interested if it is safe, to DOWNCAST (thanks Mike) an instance of a base class to a derived class under certain conditions. I think a sample is the most easy way to explain:
struct BaseA
{
void foo() const {}
double bar_member;
// no virtuals here
};
struct DerivedA : public BaseA
{
double bar(double z) {bar_member = z;return bar_member;}
// DerivedA does not add ANY member variables to BaseA.
// It also does not introduce ANY virtual functions.
};
struct BaseB
{
BaseA baseA;
};
// add extra functionality to B, to do this,
// i also need more functionality on baseA.
struct DerivedB : public BaseB
{
// is this "safe"? since BaseA and DerivedA
// should have the same memory layout?!?
DerivedA& getA() {return *static_cast<DerivedA*>(&baseA);}
double foo(double z) {return getA().bar(z);}
};
#include <iostream>
int main(int argc, char** argv)
{
DerivedB b;
// compiles and prints expected result
std::cout << b.foo(argc) << std::endl;
}
In my case, the classes BaseA and BaseB implement some kind of view concept. However, they also hold all the data members required to add further functionality in the derived classes. I know that I could implement the view to hold only a reference to the class providing the functionality. However, that would comes with some drawbacks:
I need to rewrite the whole interface for the view classes.
In my case, the Derived classes possesses an extra template argument (a callback type), which I want to have erased in the view. Hence, the view must not hold a direct reference to the classes providing functionality.
I tested my code, it works, however, I don't really trust the approach. And yes, I know I could achieve some of this with virtuals etc. but it is really performance critical...
Any ideas, hints, are welcome
Martin
for the interested people:
i changed my design the following way:
struct DerivedB : public BaseB
{
// encapsule the required extended functionality of BaseA member
struct OperateOnBaseA
{
OperateOnBaseA(BaseA& a);
double dosomething(double);
};
OperateOnBaseA a_extension;
DerivedB() :a_extension(baseA) {}
double foo(double z) {return a_extension.dosomething();}
};
As to the technical side: It is of course forbidden by the 2011 standard, 5.2.9.11, static cast. Let B be a base of D:
If the prvalue of type “pointer to cv1 B” points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
On the other hand I'd be surprised if somebody could find an implementation which doesn't just do it, because of the obvious implementations of classes, methods and static casts.
Your existing code has undefined behaviour, as stated in the other answers. You can avoid that, if you don't mind some truly horrible code, by destroying the object at baseA and creating a DerivedA at the same location, so the downcast is valid:
#include <new>
struct DerivedB : public BaseB
{
DerivedB()
{
static_assert( sizeof(BaseA) == sizeof(DerivedA), "same size" );
baseA.~BaseA();
::new(&baseA) DerivedA();
}
~DerivedB()
{
getA().~DerivedA();
::new(&baseA) BaseA();
}
DerivedA& getA() {return *static_cast<DerivedA*>(&baseA);}
double foo(double z) {return getA().bar(z);}
};
The destructor restores an object of the original type, so that when the BaseB destructor destroys its baseA member it runs the destructor of the correct type on the object.
But I would avoid doing this and redesign your classes to solve it another way.
I don't find your approad clean enough for what you're trying to do. Assuming there's a "data source type" SourceA and a "data view type" ViewB, I would go more like this:
#include <iostream>
using namespace std;
template<typename T>
class SourceA_base
{
protected:
T data;
public:
using value_type = T;
SourceA_base(T&& a) : data(std::move(a)) { }
SourceA_base(T const& a) : data() { }
void foo() const {}
};
template<typename T>
class SourceA : public SourceA_base<T>
{
using B = SourceA_base<T>;
public:
using B::B;
T bar(T z) { return B::data = z; }
};
template<typename U>
class ViewB_base
{
protected:
U&& source;
public:
using value_type = typename std::remove_reference<U>::type::value_type;
ViewB_base(U&& a) : source(std::forward<U>(a)) { }
};
template<typename U>
class ViewB : public ViewB_base<U>
{
using B = ViewB_base<U>;
using T = typename B::value_type;
public:
using B::B;
T foo(T z) { return B::source.bar(z); }
};
int main ()
{
using S = SourceA<double>;
S a{3.14};
ViewB<S&> b{a};
std::cout << b.foo(6.28) << std::endl; // compiles and prints expected result
std::cout << ViewB<S>{S{2}}.foo(4) << std::endl; // still works
}
That is, all (source/view) types are templated, views contain references, and there are no downcasts. On your reservations for the use of references:
Re-writing the whole interface: No need now, thanks to templates.
Erasing callback types: First, type erasure and performance critical applications are not always good friends. Second, you'd better have the callback erase its own underlying type(s), not the view erase the type of the callback. Each class should do its own job. Or, don't erase types and make them template parameters.
I used rvalue-references so that the whole thing works for temporaries as well, as shown in my second example. Maybe constructors are not always complete/correct here. e.g. for const references; I reality would have fully templated constructors (accepting universal references), but to make this cooperate with one-argument implicitly defined copy/move constructors is a bit trickier (needs type traits and enable_if) and I only wanted to hightlight the idea here.
You may also consider using tuples to hold data, taking advantage of their empty base optimization.
As for your original question, this downcast is something I would never do; for the technical side, see Peter Schneider's answer.
I am currently having some troubles when using boost enable_shared_from_this and multiple inheritance.
The scenario can be described as follows:
Class A implements some functionality and should inherit from enable_shared_from_this
Class B implements another functionality and should inherit from enable_shared_from_this
Class D inherits functionalities from A and B (class D : public A, public B {})
When using some class B functionality from class D I got an exception (bad_weak_ptr)
To inherit enable_shared_from_this from class D is not an option for me
I am not sure about how to solve this.
Oh, I am using Visual C++ 2010.
Expanding on Potatoswatter's solution, if you can change A and B to use a something slightly different than enable_shared_from_this. The code uses the standard library versions, but the boost implementation should be similar. Explanation below
#include <memory>
template<typename T>
struct enable_shared_from_this_virtual;
class enable_shared_from_this_virtual_base : public std::enable_shared_from_this<enable_shared_from_this_virtual_base>
{
typedef std::enable_shared_from_this<enable_shared_from_this_virtual_base> base_type;
template<typename T>
friend struct enable_shared_from_this_virtual;
std::shared_ptr<enable_shared_from_this_virtual_base> shared_from_this()
{
return base_type::shared_from_this();
}
std::shared_ptr<enable_shared_from_this_virtual_base const> shared_from_this() const
{
return base_type::shared_from_this();
}
};
template<typename T>
struct enable_shared_from_this_virtual: virtual enable_shared_from_this_virtual_base
{
typedef enable_shared_from_this_virtual_base base_type;
public:
std::shared_ptr<T> shared_from_this()
{
std::shared_ptr<T> result(base_type::shared_from_this(), static_cast<T*>(this));
return result;
}
std::shared_ptr<T const> shared_from_this() const
{
std::shared_ptr<T const> result(base_type::shared_from_this(), static_cast<T const*>(this));
return result;
}
};
So, the intent is that struct A would inherit publicly from enable_shared_from_this_virtual<A> and struct B would inherit publicly from enable_shared_from_this_virtual<B>. Since they both share the same common virtual object, there is only one std::enable_shared_from_this in the hierarchy.
When you call either classes shared_from_this, it performs a cast from enable_shared_from_this_virtual<T>* to T*, and uses the aliasing constructor of shared_ptr so that the new shared_ptr points to T* and shares ownership with the single shared pointer.
The use of the friend at the top is to prevent anyone from accessing the shared_from_this() members of the virtual base directly. They have to go through the ones provided by enable_shared_from_this_virtual<T>.
An example:
#include <iostream>
struct A : public enable_shared_from_this_virtual<A>
{
void foo()
{
shared_from_this()->baz();
}
void baz()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct B : public enable_shared_from_this_virtual<B>
{
void bar()
{
shared_from_this()->baz();
}
void baz()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct D: A, B {};
int main()
{
std::shared_ptr<D> d(new D);
d->foo();
d->bar();
return 0;
}
A shared_ptr is an observer to an invisible container object, or "control block." This container is always on the heap, never on the stack, and you can't get direct handle on it. Although shared_ptr and weak_ptr provide the only means of observation, there is still a hidden layer which owns the object. It is that hidden layer which populates enable_shared_from_this.
Multiple inheritance from enable_shared_from_this is not allowed because all the enable_shared_from_this bases would need to be initialized individually, but the control block has no way of getting a list of all base subobjects of a given type. All it can get is an ambiguous base error.
The only solution I see is to add a virtual base class of A and B which inherits from enable_shared_from_this. You might designate a particular class for this purpose:
struct shared_from_this_virtual_base
: std::enable_shared_from_this< shared_from_this_virtual_base >
{};
struct shared_from_this_base : virtual shared_from_this_virtual_base {};
struct A : shared_from_this_base { … };
struct B : shared_from_this_base { … };
But, there's another problem: you can't down-cast from a virtual base because it's ambiguous whether A or B contains the shared_from_this_virtual_base. To recover an A* or B* you would have to add those pointers to some kind of registry structure within shared_from_this_virtual_base. This would probably be populated by adding another CRTP pattern to shared_from_this_base. It's a bit more footwork than usual for C++ but I don't see any conceptual shortcut.
EDIT: Ah, the simplest way to get the downcast is to put a void* member in shared_from_this_virtual_base and then cast that to D* in whatever client code has knowledge of D. Quite workable, if not perfectly elegant. Or boost::any could provide a safer alternative.
The standard is a bit vague about how shared_from_this is supposed to be implemented, but all implementations seem to agree, because Boost provides a reference implementation.
When you create boost::shared_ptr<D> myD(new D()) the shared_ptr constructor checks if there is an unambiguous conversion from D* to enable_shared_from_this<X>* for some X (which implies that D has a base class of type enable_shared_from_this<X>). If the conversion works then a weak_ptr<X> in the base class will be set to refer to the newly-created shared_ptr.
In your code there are two possible conversions, to enable_shared_from_this<A> and enable_shared_from_this<B>, which is ambiguous, so no weak_ptr gets set to refer to myD. That means if a member function of B later calls shared_from_this() it will get a bad_weak_ptr exception, because its enable_shared_from_this<B> member was never set.