I'm making a base class, which has some methods, which are used in derived classes. This base class is something like an abstract class in the sense that apart from (protected) methods, it defines the interface (i.e. public) methods which must be implemented in derived classes. But it's not intended to be used as a polymorphic base, instead its derivatives will be used as template parameters for some other functions/functors, which would call the interface methods.
Given the above, I could use the usual way of defining abstract classes like using pure virtual functions, but there's a problem with this: the resulting derivative classes are required to have standard layout. Thus no virtual functions allowed. But still there'll be many derivatives, which will not be used until some later time, and I'd like to make the compiler check that all the methods required are implemented with the correct signature (e.g. int Derived::f(double) instead of int Derived::f(float) is not allowed).
What would be a good way to do this, taking into account the requirement of standard layout?
Here's an implementation of the CRTP pattern with a static_assert inside the interface dispatching routine:
#include <iostream>
#include <type_traits>
template<class Derived>
class enable_down_cast
{
typedef enable_down_cast Base;
public:
// casting "down" the inheritance hierarchy
Derived const* self() const { return static_cast<Derived const*>(this); }
Derived* self() { return static_cast<Derived* >(this); }
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~enable_down_cast() = default;
};
template<class FX>
class FooInterface
:
public enable_down_cast< FX >
{
using enable_down_cast< FX >::self; // dependent name now in scope
public:
int foo(double d)
{
static_assert(std::is_same<decltype(self()->do_foo(d)), int>::value, "");
return self()->do_foo(d);
}
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~FooInterface() = default;
};
Note that the above static_assert only fires if the return types of the interface and the implementation don't match. But you can decorate this code with any type trait you wish, and there are plenty of Q&As here on SO that write type traits to check for an exact function signature match between interface and implementation.
class GoodFooImpl
:
public FooInterface< GoodFooImpl >
{
private:
friend class FooInterface< GoodFooImpl > ;
int do_foo(double) { std::cout << "GoodFooImpl\n"; return 0; }
};
class BadFooImpl
:
public FooInterface< BadFooImpl >
{
private:
friend class FooInterface< BadFooImpl >;
char do_foo(double) { std::cout << "BadFooImpl\n"; return 0; }
};
int main()
{
GoodFooImpl f1;
BadFooImpl f2;
static_assert(std::is_standard_layout<GoodFooImpl>::value, "");
static_assert(std::is_standard_layout<BadFooImpl>::value, "");
f1.foo(0.0);
f2.foo(0.0); // ERROR, static_assert fails, char != int
}
Live Example on Coliru. Note that the derived class is indeed standard layout.
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.
Looking for: accessing member of a derived class from a pointer to base.
Reductio ad absurdum:
class Base
{
public:
int member_of_base;
};
class Derived : public Base
{
public:
int member_of_derived;
};
I'm currently using templates:
template <class T>
class Client
{
T* data; // T is Base or Derived
};
There are few levels of composition in the class hierarchy, so I have to carry the template type parameter through all of the hierarchy. What is the best approach to overcome this?
Obviously I cannot access the member of Derived via a pointer to Base, i.e:
Base* foo = new Derived();
foo->member_of_derived; // no go
Thus, I'm using:
Client<Base>
Client<Derived>
I'm trying to come up with a solution that works without the templates. Options that I know would work:
void* //plain old C and casting as necessary, they're all pointers
(as in memory addresses) in the machine
static_cast<Derived*>(pointer_to_base); //type safe at compile time.
wrapping the cast in a Client's template method (not to be confused with a design pattern here)
The last option seems to be the most "elegant", i.e:
template <class T>
T* get_data() const { return static_cast<T*>(data); }
However, looking here and there tells me there might exist a way unknown to me.
I saw CRTP, but that brings me back to templates, which is the original thing I want to go without.
What are the ways, or popular approaches, to achieve such a goal?
The real code uses shared_ptr, weak_ptr and enable_shared_from_this with weak_from_this. I'm looking for a type safe "polymorphic member" access.
EDIT: they're not just "ints". They can be totally different types, as in protobuf in base and Json::Value in derived. And I'm trying to use the pointers to Base/Derived, which in turn would give me access to their respective members.
A virtual getter can solve the issue for you; as data types differ, you might pack them into a std::variant.
class Base
{
// having private members probably is more appropriate
int member_of_base;
public:
using Data = std::variant<int, double>;
virtual ~Base() { } // virtual functions -> have a virtual destructor!
virtual Data getMember() // or just "member", if you prefer without prefix
{
return member_of_base;
}
};
class Derived : public Base
{
double member_of_derived;
public:
Data getMember() override
{
return member_of_derived;
}
};
std::unique_ptr<Base> foo = new Base();
foo->getMember(); // member_of_base;
std::unique_ptr<Base> bar = new Derived();
bar->getMember(); // member_of_derived;
Admitted, not yet totally without templates, std::variant is one, but I suppose in that form it is acceptable...
There are some issues with, though:
Accessing the value is not the simplest, you might consider visit function for.
More severe: Base class (or wherever else you define the variant to be used) needs to be aware of all types that might be in use, adding a new type will force to recompile all other classes.
It has the smell of bad design. Why should it be necessary for a derived class to return something different than the base that shall serve the same purpose, though???
If you can delegate the work to be done to the classes themselves, you get around all these problems:
class Base
{
int member_of_base;
public:
virtual ~Base() { }
virtual void doSomething()
{
/* use member_of_base */
}
};
class Derived : public Base
{
double member_of_derived;
public:
void doSomething() override
{
/* use member_of_derived */
}
};
The latter would be the true polymorphic approach and normally the way to go; whereas the sample above returns void, you might just do all the calculations necessary in base and derived classes until you finally get to some common data type and return this one. Example:
class Base
{
int64_t m_balance; // in 100th of currency in use
public:
virtual ~Base() { }
virtual int64_t balance()
{
return m_balance;
}
};
class Derived : public Base
{
long double m_balance; // arbitrary values in whole currency entities
public:
int64_t balance() override
{
// calculate 100th of currency, correctly rounded:
return std::llround(m_balance * 100);
}
};
Admitted, I doubt pretty much representing a balance in double (even if long) is a good idea (issues with rounding, precision, etc)...
I have the following classes:
class A {
public:
virtual std::string Serialize();
virtual void Deserialize(std::string);
template <typename T>
T* Clone()
{
std::string s = Serialize();
T* t = new T();
t->Deserialize(s);
return t;
}
};
class B : public A {
public:
std::string Serialize() { ... }
void Deserialize(std::string) { ... }
};
Now, if I want to clone B, I do the following:
B b1;
B* b2 = b1.Clone<B>();
Is there any way to remove the template type without re-implementing Clone in each and every derived classes?
I want something like this:
B b1;
B* b2 = b1.Clone();
The way to do this is with CRTP:
class A {
public:
virtual std::string Serialize();
virtual void Deserialize(std::string);
virtual A* Clone() = 0;
};
template <class T>
class HelperA : public A {
T* Clone() override
{
std::string s = Serialize();
T* t = new T();
t->Deserialize(s);
return t;
}
};
class B : public HelperA<B> {
public:
std::string Serialize() { ... }
void Deserialize(std::string) { ... }
};
These 3 level hierarchies are quite common. Basically, the top class is pure interface, as before (note: you should = 0 the other functions too). The middle class uses the CRTP pattern: it is templated on the derived typed. the idea is that by having static access to the derived type, it can automatically implement things like Clone. Then the derived type implements any implementation that cannot be done generically.
Notice that the derived-most type inherits from the CRTP class templated on itself. That's where the name comes from (Curiously Recurring Template Pattern). Of course, since inheritance is transitive B also inherits from A still, as originally, enabling the same sort of things.
Here is a full working example that you can execute: http://coliru.stacked-crooked.com/a/8f2b201a06b5abcc. I kept the code in the answer as similar to the question as possible, but in the coliru example there are a few small but important differences:
usage of owning pointers instead of raw pointers considered good practice in C++, and because smart pointers are not covariant this affects the signatures
correct use of = 0 and override, as well as const
an example of the static downcast which is kind of a signature of CRTP that didn't come up with your example
Given a base class Base that has two derived classes, DerA and DerB, can the derived classes have a member variable that is used in a Base member function, but is a different type for each class?
class Base {
* a // Declare a as *something*, so it can be used by "doWork"
template <typedef T>
void doWork(T b) { // Add another value to "a" which is of its same type
a += b; // For example; an operation that works on "a", no matter what numeric type it is
}
}
class DerA : public Base {
// Make "a" an int
}
class DerB : public Base {
// Make "a" a float
}
In practice, a will be a base struct, while DerA and DerB will have derived versions of the base struct (derivative classes will each have a derived form of the struct specific to their purpose, but each must do a simple operation on a, so it seems pointless to copy/paste that simple function for each derivative when I can just use a template function). I would just type a as the base struct type, but then I lose access to the various specialized member functions and variables that each derived struct has (if I understand inheritance correctly).
I apologize if this question is a repeat, but I don't know what this quality would be called, so Googling proved fruitless.
What you might want is the CRTP.
template<class D>
struct Base {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
template<class T>
void doWork(T b) {
self()->a += b;
}
};
struct DerA : public Base<DerA> {
int a;
};
struct DerB : public Base<DerB> {
double a;
};
Here we pass the derived type to our base class. Within the base class, you can use self()-> to access fields in the derived type. This allows basically full access to the derived type, while letting us share code in the base class.
Note that you cannot pass DerA and DerB around as a Base this way. If you want that, you need a virtual method doWork, and virtual template methods don't exist.
CRTP stands for the curiously repeating template pattern, which I imagine is named because it is strange, it involves repeating a type, and it keeps on showing up in strange corners as being useful.
Type erasure probably won't work either, as you want to dispatch the type erasure from two different spots in the code base (the double dispatch problem: you need a centralized list of types supported to do the type Cartesian product on).
To expand on that, in order to support a+=b where both a and b are arbitrary types, you would have to expand over all types twice over, including types that are never mutually visible at the same spot in a compilation unit. That isn't possible.
If you need a common base, and there are only some types you pass to doWork, here is how you do it:
struct Base {
virtual void doWork( double ) = 0;
virtual void doWork( int ) = 0;
virtual void doWork( long long ) = 0;
};
template<class D>
struct Base_helper:Base {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
template<class T>
void doWork_impl(T b) {
self()->a += b;
}
void doWork( double x ) override { doWork_impl(x); };
void doWork( int x ) override { doWork_impl(x); };
void doWork( long long x ) override { doWork_impl(x); };
};
struct DerA : public Base_helper<DerA> {
int a;
};
struct DerB : public Base_helper<DerB> {
double a;
};
note that every version of doWork must be valid to call on each of the Ders, as the Base_helper instantiates all of them.
If the kind of type passed to doWork is unbounded, yet the types of Der is bounded, you can do something like the above only backwards. It gets awkward, however. Your best bet in that kind of situation is to use a boost::variant type solution.
I guess you want to achieve something like this:
template<typedef T>
class Base {
T a;
void doWork(T b) { // Add another value to "a" which is of its same type
a += b; // For example; an operation that works on "a", no matter what numeric type it is
}
}
class DerA : public Base<int> {
}
class DerB : public Base<float> {
}
Or you can dump classes DerA and DerB entirely and use typedefs instead:
typedef Base<int> DerA;
typedef Base<float> DerB;
This can be easily solved with a CRTP-like pattern:
template<class D> // Base class is templated
class Base {
public:
D a;
void doWork(D b) {
a += b;
}
};
class DerA : public Base<int> {};
class DerB : public Base<float> {};
Live Example
Edit: in case you need only one common base (Base<int> is a completely different type from Base<float>) you might use an interface class and have Base inherit from it.
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/