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.
Related
I am trying to create an abstract class template (InstanceTracker) that classes can inherit from if they need functionality to perform operations on all of their instances. The class holds a static vector of pointers to 'T', and every time an InstanceTracker constructor is run, I push back a new pointer to the vector. I do this through a purely virtual getDerivedPtr() method that returns 'T*', that every class that derives from InstanceTracker has to implement with return this;. You can probably already see what is wrong what this though. You can never call a purely virtual function from a base constructor - since it doesn't exist yet. How can I find a way around this problem for my InstanceTracker class? Here's the code for the class:
#pragma once
#include <vector>
template <typename T>
class InstanceTracker
{
public:
InstanceTracker() noexcept
{
allInstances_.push_back(getDerivedPtr());
}
InstanceTracker(const InstanceTracker& source) noexcept
: InstanceTracker()
{
}
InstanceTracker(const InstanceTracker&& source) noexcept
: InstanceTracker()
{
}
virtual ~InstanceTracker() noexcept
{
auto it = std::find(allInstances_.begin(), allInstances_.end(), this);
int index = it - allInstances_.begin();
allInstances_.erase(allInstances_.begin() + index);
}
virtual T* getDerivedPtr() = 0;
protected:
static std::vector<T*> allInstances_;
};
If you want to try to run the code and see why it doesn't work at the moment, here's a simple class that inherits from InstanceTracker:
class Derived1 : public InstanceTracker
{
public:
Derived1* getDerivedPtr() override
{
return this;
}
};
You'd probably be better off using composition rather than inheritance, but I'll assume you have have a good reason to prefer inheritance here.
The difficulty is that, when a base class constructor is run, the this pointer is a pointer to an instance of the base class only. The derived instance doesn't even exit yet. (Likewise, on destruction, the derived portion of the object has already been uninitialized). So if you call a virtual method, you'll get the base class implementation rather than the derived class's implementation. In your case, the base class implementation doesn't even exist, so you're stuck.
You can probably get away with casting the base class's this pointer to a pointer to the derived class, but that's not guaranteed to work and probably involves undefined behavior.
One way to solve this is to store pointers to the base type (InstanceTracker *) rather the pointers to the derived type. Then your getDerivedPtr method doesn't need to be virtual, and it can do the cast when it's safe.
template <typename T>
class InstanceTracker {
public:
InstanceTracker() noexcept {
allInstances_.push_back(this);
}
// other constructors elided for space
virtual ~InstanceTracker() noexcept {
std::erase(
std::remove(allInstances_.begin(), allInstances_.end(),
this),
allInstances.end());
}
T* getDerivedPtr() {
return static_cast<T*>(this); // downcast
}
protected:
// allInstances_ stores base class pointers
static std::vector<InstanceTracker*> allInstances_;
};
Notes:
If you use RTTI, run-time type identification, you can use dynamic_cast instead of static_cast. You should not use a reinterpret_cast because the compiler might need to adjust the base pointer as part of the cast.
You're likely to run into problems if you create an instance of a derived type as const.
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.
It is easier to explain on an example so,
class base {
//....
}
class derived1 : public base {
//...
}
In my library, there is a pointer of base class. The user of the library have to make classes derived from either base or derived1 and assign pointer to that class.
How can I check what class is user-defined class derived from?
I have some remarks on the proposed compile-time x runtime solutions. In addition to when they are evaluated, is_base_of and dynamic_cast have different requirements and their answers can be different.
(1) First of all (as pointed out by others) to use dynamic_cast, base and derived classes must be polymorphic (must have at least one virtual method). is_base_of doesn't require the types to be polymorphic.
(2) The operands of is_base_of are both types whereas dynamic_cast needs a type (inside < >) and an object (inside ( )).
(3) dynamic_cast and is_base_of can give different answers (or one can compile while the other doesn't) depending on the type of inheritance (public vs protected or private). For instance consider:
struct B { virtual ~B() {} }; // polymorphic, so it can be used in a dynamic_cast
struct D1 : public B {}; // polymorphic by (public) inheritance
struct D2 : private B {}; // polymorphic by (private) inheritance
D1 d1;
D2 d2;
We have
static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");
assert(dynamic_cast<B*>(&d1));
assert(!dynamic_cast<B*>(&d2)); // Notice the negation.
Actually the last line yields a compiler error in GCC (error: 'B' is an inaccessible base of 'D2'). VS2010 does compile it (yielding just a warning similar to GCC's error message).
(4) The requirements on the classes being polymorphic can be relaxed through an exception handling trick. Consider:
struct B { }; // not polymorphic
struct D1 : public B {}; // not polymorphic
struct D2 : private B {}; // not polymorphic
D1 d1;
D2 d2;
template <typename B, typename D>
const B* is_unambiguous_public_base_of(const D* obj) {
try {
throw obj;
}
catch (const B* pb) {
return pb;
}
catch (...) {
}
return nullptr;
}
Then we have
static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");
assert((is_unambiguous_public_base_of<B>(&d1)));
assert(!(is_unambiguous_public_base_of<B>(&d2))); // Notice the negation.
It's worth mentionning that is_unambiguous_public_base_of is far slower than dynamic_cast and (this became more obvious after the renaming mentioned in the update below) always returns a nullptr for downcasts:
B* b1 = &d1;
assert(dynamic_cast<D1*>(b1)); // Requires D1 and B to be polymorphic.
assert(!(is_unambiguous_public_base_of<D1>(b1))); // Notice the negation.
A bit outdated reference on this trick is available in the following links:
Part 1, Part 2 and code
Disclaimer: the implementation of is_unambiguous_public_base_of above is just a draft to make the point and it doesn't handle const and volatile qualifications properly.
Update: In a previous version of this post is_unambiguous_public_base_of was named my_dynamic_cast and this was a source of confusion. So I renamed it to a more meaningful name. (Thanks to Jan Herrmann.)
You could use dynamic_cast.
if (dynamic_cast<DerivedClass*>(ptr)) {
std::cout << "Class is derived from DerivedClass.";
}
Check if class is derived from a specific class (compile time)
You can use std::is_base_of:
#include <type_traits>
....
const bool isBase = std::is_base_of<base, TheOtherClass>::value;
isBase is true if TheOtherClass is derived from base.
I think the answer to this question is very difficult. Of course there is std::is_base_of and dynamic_cast. Both provide you with some very limited information. The third option is function overloading. With all of those techniques you can choose a special path in your code which should be executed.
std::is_base_of can be interpreted in a boolean context and it is derived from either std::true_type or std::false_type. This fact makes it possible to use it as paramter for a function and use compile time polymorphism via function overloading. This first example shows how to use it in a boolean context, but you don't have any further specific type information. So compilation will fail in most circumstances (see here for a further description):
template<class T>
void do_it1(T const& t) {
if (std::is_base_of<T,derived1>::value) {
// we have a derived1
} else {
// we have a base
}
}
The second version is simple function overloading. Here compile time polymorphism is used but all runtime type information is lost (except virtual functions and dynamic_cast are used):
void do_it2(Base const& b) {
// we have a base your algorithm for base here
}
void do_it2(Derived2 const& d) {
// Derived algorithm here
}
Now the third version combines both:
template<class T>
void do_it3_impl(T const& t, std::true_type) {
// here t will be of a type derived from derived1
}
template<class T>
void do_it3_impl(T const& t,std::false_type) {
// here t will be of type not derived from derived1
}
template<class T>
void do_it_3(T const& t) {
do_it3_impl(t, std::is_base_of<T,derived1>()); // here we forward to our impl
}
The third variant is normaly used for header only libraries which don't use runtime poylmorphism (search for std::advance for an excample).
Now to runtime polymorphism. Here you have the dynaminc_cast variant:
void do_it4(Base const* ptr)
if (derived1 const* obj = dynamic_cast<derived*>(ptr)) {
// here we have obj with type derived1*
} else {
// here we have only base
}
If this variant is not fast enough you can implement your onw cast to derived1:
class derived1;
class base {
// as above
public:
virtual derived1 const* to_derived1() const {
return 0;
}
};
class derived1
: public base
{
// ...
virtual derived1 const* to_derived1() const {
return this;
}
};
void do_it5(Base const* ptr)
if (derived1 const* obj = ptr->to_derived1() {
// here we have obj with type derived1*
} else {
// here we have only base
}
This is fast but it scales very well for only very few (approximately 1) derived classes.
Last but not least you should think about your class design and deside what methods to make virtual and implement in base, derived1 or other classes. You should definitly look for strategy pattern.
You can do this in several ways. The most common ones as the others have pointed out are dynamic_cast<> and std::is_base_of. The latter is used at compile time, while dynamic_cast<> can be used at runtime.
HOWEVER, dynamic_cast<> will only work if your source class is polymorphic (i.e. has at least one virtual function - it can be a method or its destructor). If not, the compiler will trigger an error.
The compiler will only accept pointers to classes derived from your base class if your library functions takes pointers to the base class. My answer is with a classical approach type safety will handle it. To my experience that kind of type checking is enough. Having 25 years experience in the industry I question the need to do this check. Maybe such a fundamental question is not welcome? I would like to see the justification to having the need to do this kind of upcast. I never have to do that. The opposite, i.e. a down cast I need quite frequently.
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.
Say you have a base class Dep for a tree of classes. There is a virtual method Dep* Dep::create() that I want to be implemented by every single leaf class. Is there any way to enforce this?
Note: The problem here is that there could be intermediate classes (say class B : public A : public Dep) implementing this method (A::create) by accident or because they think they are leaf classes, but are in fact subclassed themselves.
The question ends here.
Context
If you are curious why I need this; I have a class Master which has Dep objects of unknown concrete type. If Master is duplicated, I need to come up with a matching clone of the Dep instance. Next best thing to do is the virtual constructor idiom, which introduces precisely this problem.
Additionally, I cannot even catch this (other then by crashing horribly), because for obscure reasons, people that have more to say than me, have outlawed dynamic_cast in this project (perhaps this is a good decision; But anyways a completely different discussion).
C++ provides no way to keep a class from inheriting from your class, and there is no way to make a particular class in the inheritance hierarchy implement a method. The only rule is that somewhere in the inheritance hierarchy above a particular class (not necessarily in the leaf) all virtual functions must have an implementation for that class to be instantiatable.
For instance, A could inherit from Def and implement all it's [pure] virtual methods. Then if B inherits from A, it doesn't have to implement anything. There's no way to keep that from happening.
So the answer is no, there is no way to enforce this.
Using curiously recurring template fun, you can achieve something quite similar:
template<typename T>
class Cloneable : public T, public Dep
{
private:
Cloneable<T>() : T() { }
public:
static Cloneable<T>* Create() { return new Cloneable<T>(); }
Cloneable<T>* clone() { return new Cloneable<T>(*this); }
};
Instead of deriving from Dep and instantiating via new MyType, use Cloneable<MyType>::Create. Since Cloneable<MyType> is derived from MyType, you can use the instance the same way you would use any MyType, except that it is now guaranteed to have Dep::clone.
Additionally your Master should not accept an instance of type Dep, but enforce that it is a Cloneable<T>. (Replace your orignial function by a simple function template that enforces this.) This guarantees that any Dep inside the master has a correctly implemented clone function.
Since Cloneable<MyType> has no public constructor, it cannot be inherited, however your actual MyType can be further inherited and used just as before.
Did TPTB outlaw all RTTI, or only dynamic_cast<>()? If you can use RTTI, then you can enforce the existence of the method as a postcondition of calling it:
#include <typeinfo>
#include <cassert>
#include <iostream>
#include <stdexcept>
class Base {
protected:
virtual Base* do_create() = 0;
virtual ~Base() {}
public:
Base* create() {
Base *that = this->do_create();
if( typeid(*this) != typeid(*that) ) {
throw(std::logic_error(std::string() +
"Type: " +
typeid(*this).name() +
" != " +
typeid(*that).name()));
}
return that;
}
};
class Derive1 : public Base {
protected:
Base* do_create() { return new Derive1(*this); }
};
class Derive2 : public Derive1 {};
void f(Base*p) { std::cout << typeid(*p).name() << "\n"; }
int main() {
Derive1 d1;
Base *pD1 = d1.create(); // will succeed with correct semantics
Derive2 d2;
Base *pD2 = d2.create(); // will throw exception due to missing Derive2::do_create()
}
If you control the base class AbstractDep then you can enforce that concrete leaf classes must be created by using a class template WithCloning. This leaf can then be sealed so that it cannot be inherited. Or more precisely, instances cannot be created of a derived class.
class AbstractDep
{
template< class Type > friend class WithCloning;
private:
enum FooFoo {};
virtual FooFoo toBeImplementedByLeafClass() = 0;
public:
virtual AbstractDep* clone() const = 0;
};
template< class Type > class WithCloning;
class Sealed
{
template< class Type > friend class WithCloning;
private:
Sealed() {}
};
template< class Type >
class WithCloning
: public Type
, public virtual Sealed
{
private:
AbstractDep::FooFoo toBeImplementedByLeafClass()
{
return AbstractDep::FooFoo();
}
public:
virtual WithCloning* clone() const
{
return new WithCloning( *this );
}
};
typedef WithCloning<AbstractDep> Dep;
class AbstractDerivedDep
: public AbstractDep
{
// AbstractDep::FooFoo toBeImplementedByLeafClass(); // !Not compile.
public:
};
typedef WithCloning<AbstractDerivedDep> DDep;
struct Foo: Dep {}; // !Does not compile if instantiated.
int main()
{
Dep d;
//Foo f;
}
If the classes require more than default construction then that most be solved additionally.
One solution is then to forward an argument pack from the WithCloning constructor (there is an example C++98 implementation on my blog, and C++0x supports that directly).
Summing up, to be instantiable the class must be WithCloning.
Cheers & hth.,
when you say that they are unknown, i presume they still inherit from a common base class /interface right?
only thing i can think of you can use to force is on the virtual base class add
virtual Base* clone() {
assert( 1==0 ); //needs to be overriden
}
so you are forced to override, but this is only detected at run-time when trying to call clone on a instance of a class that is missing the override
even if you are not allowed to use dynamic_cast or RTTI, you can still enable it for debug purposes locally on your build, if that will help you find the typeid of offending classes
it sounds like you are familiar with the clone pattern, but i'll post it quietly in here, and we can forget about it:
http://www.cplusplus.com/forum/articles/18757/