I want to make sure only smart pointers are build from my classes so i made all constructors protected.
To create objects i build this "Buildable"-Policy:
template <typename T>
class Buildable
{
public:
template<typename ...Args>
static QSharedPointer<T> buildObject(Args&&... all)
{
return QSharedPointer<T>( new T(std::forward<Args>(all)...) );
}
};
If i use this this policy in a base class, all goes well.
But when i use it in base and a derived class like this:
class A : public Buildable<A> {}
class B : A, public Buildable<B>{}
the compiler argues: Error: member 'buildObject' found in multiple base classes of different types
I don't know how to solve this problem. Any ideas?
Cause of the error
This is because the multiple inheritance here:
class B : A, public Buildable<B>{};
It causes class B to inherit from Buildable<A> and from Buildable<B> which both contain a buildObject() overload. Unfortunately, both overloads differs only by the return type. This is not allowed.
Design issue
Unfortunately, you can't avoid this unless you could smuggle an additional parameter to buildObject(), which could permit the compiler to use proper type derivation to resolve avoid ambiguity.
But do you really intend to have multiple inheritance in your design here ? If your classes would be polymorphic, couldn't you use a class B defined as follows:
class B : public A {}; // inherits from Buildable A
...
QSharedPointer<A> b = B::buildObject(); //
Alternative design
The alternative could be to put the building class at the bottom of the derivation, to avoid the conflicts. Make your constructors for classes A and B protected, and use this template class :
// (I used here shared_ptr instead of QSharedPointer for testing purpose)
template <typename T>
class Builder : public T
{
public:
Builder() = delete;
Builder (const Builder&) = delete;
template<typename ...Args>
static shared_ptr<T> buildObject(Args&&... all)
{
return make_shared<T>(std::forward<Args>(all)...) ;
}
};
class A { };
class B : public A {}; // Normal class hierarchy.
// can't be instantiated if ctor are protected.
shared_ptr<A> a = Builder<A>::buildObject();
shared_ptr<B> b = Builder<B>::buildObject();
One easy solution to the design problem is to make buildObject a freestanding function template, that you make a friend of each user class.
In order to simplify friend declarations you may want to put that function template in a class.
Then it's very much like your existing code, except there's no inheritance from the factory class:
#include <memory> // std::shared_ptr
#include <utility> // std::forward
namespace my{
using std::forward;
using std::shared_ptr;
template< class Class >
struct Make_
{
template< class... Args >
static auto instance( Args&&... args )
-> shared_ptr<Class>
{ return shared_ptr<Class>( new Class( forward<Args>( args )... ) ); }
};
class A
{
template< class > friend struct Make_;
protected:
A( int ) {}
};
class B
: public A
{
template< class > friend struct Make_;
protected:
B( int x ): A( x ) {}
};
} // namespace my
auto main() -> int
{
using namespace my;
auto p = Make_<B>::instance( 42 );
}
General solutions to the immediate technical problem of providing a covariant function without repeating its definition, include:
A macro (that expands to the function definition).
This is what I recommend, if you feel that it absolutely has to be a member function. It's one of the few legitimate uses of macros.
Middle-man inheritance.
Essentially instead of inheriting directly from a Base and also from a mixin, you inherit from the mixin and ask it to inherit from Base. You need to forward constructor arguments from the mixin.
Dominance in virtual inheritance hierarchy.
A really ugly and complex solution. Don't go there. But it's a technical possibility.
Finally there is non-solution of using a function that returns a (smart) pointer to base class. Where the client code has to cast it down. It's really ungood in its own way, but I mention it for completeness.
You could inherit from QEnableSharedFromThis (see here for further details).
As an example:
class C: public QEnableSharedFromThis<C> {
C() = default;
// all the other constructors
public:
template<typename ...Args>
static QSharedPointer<C> create(Args&&... all) {
// refers one of the available constructors
return QSharedPointer<C>(new C{std::forward<Args>(all)...});
}
QSharedPointer<C> getSharedFromThis() {
return sharedFromThis();
}
};
You can use it as a base class for your hierarchy.
Related
Is it possible to check, through a base class pointer, whether different derived template classes are specialization of the same template class?
This is achievable through introducing an intermediate non-template base-class. However, i would like to know whether this pattern is avoidable when the sole purpose of this intermediate class is for identification:
class A{}
class B_base : public A{}
template<T>
class B : public B_base {}
// There may be other derived classes of A
template<T>
class C: public A{}
void main() {
// ... some vector of pointers to A derived objects
std::vector<A*> v;
for(auto& i : v){
// Check whether i is any specialization of B through a
// dynamic_cast to the intermediate class
if(dynamic_cast<B_base*>()){
// This is a B_base object,
}
}
}
Ideally, i would like something like this, to avoid the intermediate class.
class A{}
template<T>
class B : public A{}
// There may be other derived classes of A
template<T>
class C: public A{}
void main() {
// ... some vector of pointers to A derived objects
std::vector<A*> v;
for(auto& i : v){
// Check whether i is any specialization of B
if(templateTypeId(i) == templateTypeId(B*)){
// This is a B object with some unknown specialization
}
}
}
Different specializations of a template are entirely unrelated types for most purposes. Template argument deduction can deduce a template and its arguments from such a type, but that happens entirely at compile time. There is no guaranteed run time information that can tell whether a class is a specialization of a given template, whether two classes are specializations of the same template, etc.
So you would need to set up a way to test this yourself, but your intermediate class method is not the only option. The most straightforward way would be to put a way to test it into the base A class:
class A {
public:
virtual ~A() = default;
virtual bool is_B() const noexcept { return false; }
};
template <class T>
class B : public A {
public:
bool is_B() const noexcept override { return true; }
};
Though this gets a bit ugly if there are several different B-like categories to test for, and doesn't work if it should be possible to extend A with new subtypes, and then test for those subtypes in a similar way.
Another idea would be to associate the type check with an object address:
struct type_tag {
constexpr type_tag() = default;
type_tag(const type_tag&) = delete;
type_tag& operator=(const type_tag&) = delete;
};
class A {
public:
virtual ~A() = default;
virtual bool matches_type(const type_tag&) const
{ return false; }
};
inline constexpr type_tag B_tag{};
template <class T>
class B {
public:
bool matches_type(const type_tag& tag) const override
{ return &tag == &B_tag; }
};
This pattern also allows for categories of subtypes that don't come from just one template. It also doesn't prevent a new class from "lying" about its own type, if that might be a concern, but it might be best not to try to prevent that, but let any implemented derived class be responsible for its own behavior, which might mean it wants to act "almost exactly like" some other type.
May be a better design is to add required virtual functions to interface A, so that you can invoke them directly on A* without guessing the derived class. The latter is an anti-pattern because it defeats the purpose of polymorphism: the idea that a piece of code can work with object of different classes without knowing their exact type. You may as well put objects of different types into different containers and not use ploymorphism based on virtual functions at all.
I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?
Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.
If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.
Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};
I am trying to achieve that certain objects within my application can only be constructed as shared_ptr's by a call to a static method called "create".
Of course I could do this by directly adding the static 'create' method to all the respective class. However, this would mean I have to repeat very similar code in almost all my classes. A macro would work, but I do not find this very elegant.
I came up with an alternative way of doing this by deriving all classes from a templated 'BaseObject' class that implements the 'create' method and returns the pointer. This almost works, except that std::make_shared cannot access the constructor of its child class when it is protected.
The non-solution would be to make the child class constructor public (see (1) in the example below). But now Foo can be normally constructed again and this would defeat the entire point. An alternative solution would be to friend BaseObject in the child class and make use of shared_ptr directly (see (2) in the example).
Both solutions put extra burden on the implementer of the child class. Since they have to either find an alternative way of making the constructor non-public or put a friend declaration. The (2) solution has the additional problem of not being able to use the more efficient make_shared.
My question: is there a better way of doing this?
template<class T>
class BaseObject
{
public:
typedef std::shared_ptr<T> SharedPtr;
template<class... Args>
static typename BaseObject<T>::SharedPtr create(Args&&... args)
{
return std::make_shared<T>(args...);
//return std::shared_ptr<T>(new T(args...)); (2)
}
};
class Foo : public BaseObject<Foo>
{
//friend BaseObject<Foo>; (2)
protected: //public (1)
Foo(int a = 0) : m_foo(a) {}
private:
int m_foo;
};
int main(int argc, char* argv[])
{
Foo::SharedPtr bla = Foo::create(1);
return 0;
}
Update:
They pass-key idiom seems to provide the best solution for me at this moment:
template<class T>
class BaseObject
{
public:
typedef std::shared_ptr<T> SharedPtr;
class Key
{
friend class BaseObject<T>;
Key() {}
};
template<class... Args>
static typename BaseObject<T>::SharedPtr create(Args&&... args)
{
return std::make_shared<T>(Key(), args...);
}
};
class Foo : public BaseObject<Foo>
{
public:
Foo(BaseObject<Foo>::Key, int a = 0) : m_foo(a) {}
private:
int m_foo;
};
The good things:
Only possible to create an object of Foo as a shared_ptr through
Foo::create.
No need to add complex friend declarations in Foo.
std::make_shared still works.
The only problem with this solution is the requirement to have 'Key' as a first argument in the constructor. But I can live with that.
Better is subjective, but I believe it would be a little more intuitive if you would make your constructor private, and std::make_shared a friend function. This way the only function that could create your object would be std::make_shared, and you could write
std::shared_ptr<Foo> ptr = std::make_shared<Foo>(12);
instead of:
Foo::SharedPtr bla = Foo::create(1);
So any future reader of your code would understand what you mean withou actually looking at the Foo class.
UPDATE
I have tried out what I wrote, but did not really work. Here is an answer for a similar question instead, which most likely also aplies for your question:
Using make_shared with a protected constructor + abstract interface
UPDATE 2
Here is how you can make it work (VC++2013)
#include <memory>
using namespace std;
class Foo
{
protected:
Foo(int a = 0) : m_foo(a) {}
private:
int m_foo;
friend shared_ptr<Foo> make_shared<>();
friend class _Ref_count_obj<Foo>;
};
int main()
{
shared_ptr<Foo> foo = make_shared<Foo, int>(12);
return 0;
}
_Ref_count_obj is internally used by make_shared, that's why you need to befriend that too.
I've been using the Curiously recurring template pattern The general code looks like this:
template <typename T> void genericFunction(T &);
template <typename T> struct Functionality {
void genericMethod() {
genericFunction(*((T *)this)) ;
}
};
struct Klass : public Functionality<Klass> {};
void main() {
Klass obj ;
obj.genericMethod();
}
template <> void genericFunction<Klass>(Klass &obj) {
//do stuff with Klass &obj here
}
I ran into an error today which cost me about 90 minutes of hair-pulling fustration, this error was caused by using an incorrect template parameter for my base class inheritance declaration, somewhat like so:
struct Klass : public Functionality<SomeOtherKlass> {}; //SomeOtherKlass wrong!!!
I'd like to enhance my code so that this mismatch between the derived class and the base class template parameter is detected (runtime, compile time, anytime :) ), is this even possible?, thanks.
You could assert the relation in e.g. genericMethod() using Boost or C++11 features:
BOOST_STATIC_ASSERT(( boost::is_base_of<Functionality<T>, T>::value ));
... although that is assuming that the other class doesn't derive from Functionality<T> as well.
An alternative could be to assert the relation at runtime in test-builds:
template <typename T> struct Functionality {
#ifdef TEST_BUILD
virtual ~Functionality() {}
#endif
void genericMethod() {
#ifdef TEST_BUILD
assert(dynamic_cast<T*>(this));
#endif
genericFunction(*((T *)this)) ;
}
};
Note that the test won't work inside constructors and destructors
In C++11, the following should work:
template<typename T> class Base
{
friend T; // allowed in C++11
private:
~Base() {}
public:
// ...
};
class Derived: public Base<Derived> {}; // OK
class WronglyDerived: public Base<Derived> {}; // Error: destructor of base class is private
You could use a dynamic_cast, which will return null if you have the wrong parameter type. (You'll need at least one virtual function in the base for this to work - the destructor, say.)
If you're worried about efficiency, boost has a polymorphic_cast which does a dynamic cast in debug mode but a static cast for production.
(And in any case it would be nice to avoid the use of the C-style cast.)
Suppose you add a templated constructor to the base that takes a pointer to arbitrary type;
template<class U> Functionality(U *) { ... }
Then each derived class's constructor can pass its this pointer to the constructor, and in the body of the constructor you just static assert that U and T are the same type.
The constructor parameter is never actually used so should be optimised out entirely. And if this is the only base class constructor you can't forget to call it. The only problem would be if you passed something other than this.
The most tangible suggestion thus far is to use dynamic_cast to expose malformed inheritance declarations in the Base class constructor, like so:
#include <iostream>
template <typename T> struct Base {
Base() {
std::cout<<dynamic_cast<T *> (this)<<std::endl;
}
virtual void iampolymorphic(){}
};
struct Decoy {} ;
struct Pass : public Base<Pass>{}; //correct
struct Fail : public Base<Decoy>{}; //incorrect
int main() {
Pass p ;
Fail f ;
return 1 ;
}
This code compiles on g++ 4.6.1, Amd64 Xubuntu 11.10. The output for both dynamic cast operations is a null pointer. Comments, criticisms and observations are welcomed.
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/