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.
Related
Suppose I have the class
class A {
protected:
int x,y;
double z,w;
public:
void foo();
void bar();
void baz();
};
defined and used in my code and the code of others. Now, I want to write some library which could very well operate on A's, but it's actually more general, and would be able to operate on:
class B {
protected:
int y;
double z;
public:
void bar();
};
and I do want my library to be general, so I define a B class and that's what its APIs take.
I would like to be able to tell the compiler - not in the definition of A which I no longer control, but elsewhere, probably in the definition of B:
Look, please try to think of B as a superclass of A. Thus, in particular, lay it out in memory so that if I reinterpret an A* as a B*, my code expecting B*s would work. And please then actually accept A* as a B* (and A& as a B& etc.).
In C++ we can do this the other way, i.e. if B is the class we don't control we can perform a "subclass a known class" operation with class A : public B { ... }; and I know C++ doesn't have the opposite mechanism - "superclass a known class A by a new class B". My question is - what's the closest achievable approximation of this mechanism?
Notes:
This is all strictly compile-time, not run-time.
There can be no changes whatsoever to class A. I can only modify the definition of B and code that knows about both A and B. Other people will still use class A, and so will I if I want my code to interact with theirs.
This should preferably be "scalable" to multiple superclasses. So maybe I also have class C { protected: int x; double w; public: void baz(); } which should also behave like a superclass of A.
You can do the following:
class C
{
struct Interface
{
virtual void bar() = 0;
virtual ~Interface(){}
};
template <class T>
struct Interfacer : Interface
{
T t;
Interfacer(T t):t(t){}
void bar() { t.bar(); }
};
std::unique_ptr<Interface> interface;
public:
template <class T>
C(const T & t): interface(new Interfacer<T>(t)){}
void bar() { interface->bar(); }
};
The idea is to use type-erasure (that's the Interface and Interfacer<T> classes) under the covers to allow C to take anything that you can call bar on and then your library will take objects of type C.
I know C++ doesn't have the opposite mechanism - "superclass a known
class"
Oh yes it does:
template <class Superclass>
class Class : public Superclass
{
};
and off you go. All at compile time, needless to say.
If you have a class A that can't be changed and need to slot it into an inheritance structure, then use something on the lines of
template<class Superclass>
class Class : public A, public Superclass
{
};
Note that dynamic_cast will reach A* pointers given Superclass* pointers and vice-versa. Ditto Class* pointers. At this point, you're getting close to Composition, Traits, and Concepts.
Normal templates do this, and the compiler will inform you when you use them incorrectly.
instead of
void BConsumer1(std::vector<B*> bs)
{ std::for_each(bs.begin(), bs.end(), &B::bar); }
void BConsumer2(B& b)
{ b.bar(); }
class BSubclass : public B
{
double xplusz() const { return B::x + B::z; }
}
you write
template<typename Blike>
void BConsumer1(std::vector<Blike*> bs)
{ std::for_each(bs.begin(), bs.end(), &Blike::bar); }
template<typename Blike>
void BConsumer2(Blike& b)
{ b.bar(); }
template<typename Blike>
class BSubclass : public Blike
{
double xplusz() const { return Blike::x + Blike::z; }
}
And you use BConsumer1 & BConsumer2 like
std::vector<A*> as = /* some As */
BConsumer1(as); // deduces to BConsumer1<A>
A a;
BConsumer2(a); // deduces to BConsumer2<A>
std::vector<B*> bs = /* some Bs */
BConsumer1(bs); // deduces to BConsumer1<B>
// etc
And you would have BSubclass<A> and BSubclass<B>, as types that use the B interface to do something.
There is no way to change the behaviour of a class without changing the class. There is indeed no mechanism for adding a parent class after A has already been defined.
I can only modify the definition of B and code that knows about both A and B.
You cannot change A, but you can change the code that uses A. So you could, instead of using A, simply use another class that does inherit from B (let us call it D). I think this is the closest achievable of the desired mechanism.
D can re-use A as a sub-object (possibly as a base) if that is useful.
This should preferably be "scalable" to multiple superclasses.
D can inherit as many super-classes as you need it to.
A demo:
class D : A, public B, public C {
public:
D(const A&);
void foo(){A::foo();}
void bar(){A::bar();}
void baz(){A::baz();}
};
Now D behaves exactly as A would behave if only A had inherited B and C.
Inheriting A publicly would allow getting rid of all the delegation boilerplate:
class D : public A, public B, public C {
public:
D(const A&);
};
However, I think that could have potential to create confusion between code that uses A without knowledge of B and code that uses knows of B (and therefore uses D). The code that uses D can easily deal with A, but not the other way 'round.
Not inheriting A at all but using a member instead would allow you to not copy A to create D, but instead refer to an existing one:
class D : public B, public C {
A& a;
public:
D(const A&);
void foo(){a.foo();}
void bar(){a.bar();}
void baz(){a.baz();}
};
This obviously has potential to mistakes with object lifetimes. That could be solved with shared pointers:
class D : public B, public C {
std::shared_ptr<A> a;
public:
D(const std::shared_ptr<A>&);
void foo(){a->foo();}
void bar(){a->bar();}
void baz(){a->baz();}
};
However, this is presumably only an option if the other code that doesn't know about Bor D also uses shared pointers.
This seems more like static polymorphism rather dynamic. As #ZdeněkJelínek has already mentioned, you could you a template to ensure the proper interface is passed in, all during compile-time.
namespace details_ {
template<class T, class=void>
struct has_bar : std::false_type {};
template<class T>
struct has_bar<T, std::void_t<decltype(std::declval<T>().bar())>> : std::true_type {};
}
template<class T>
constexpr bool has_bar = details_::has_bar<T>::value;
template<class T>
std::enable_if_t<has_bar<T>> use_bar(T *t) { t->bar(); }
template<class T>
std::enable_if_t<!has_bar<T>> use_bar(T *) {
static_assert(false, "Cannot use bar if class does not have a bar member function");
}
This should do what you'd like (i.e. use bar for any class) without having to resort to a vtable lookup and without having the ability to modify classes. This level of indirection should be inlined out with proper optimization flags set. In other words you'll have the runtime efficiency of directly invoking bar.
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.
I have an doubt, with C++ redefinition. I assign memory in Derived class, so I need that this memory is reserved in Base class. So, I need considered that the attibute in the Base class is the same that the attribute in the Derived class, and I don't know is that is possible in C++.
class Base {
protected:
float * a;
Base() {}
public:
virtual void reset() {
a = 0;
}
virtual void exec() {
printf("Memory a: %x\n",a);
}
};
class Derivada: virtual public Base {
protected:
float * a;
Derivada() {}
virtual void reset() {
a = new float[256];
}
};
int main() {
Derivada *hija= new Derivada();
hija->reset();
hija->exec();
delete hija;
}
I really need do overloading, because it is an example of my real problem. I have the same test (Derived an main, code), for two different class Base, one in each branch, of my two branchs, of CVS.
In one of this class Base, I have this attributes, an in the other class Base, I don't have this attributes, so I have to put it, in Derived class, for compiling.
I wouldn't like to have to make two different test codes, so I need override the attribute
You could do something like this (but requires C++11):
#include <type_traits>
// A way to check for 'attr' data member presence/absence using SFINAE
template<class T> constexpr auto missing_attr(T) -> decltype(T::attr, bool())
{
return false;
}
constexpr bool missing_attr(...) { return true; }
struct Base { /* There might be (or not) a float data member 'attr' */ };
template<bool> struct Inject;
template<> struct Inject<true> { float attr = 0.0; };
template<> struct Inject<false> {};
struct Derived : public Base, protected Inject<missing_attr(Base())>
{
void do_something_with_attr()
{
// Derived has only one 'float attr' (it can be from Base or from Inject).
a *= a;
}
};
There are other ways to detect if a data member exists, e.g. the member detector idiom (C++03 compatible).
Do not redeclare the member the the derived class. The word "protected" ensures visibility.
If you redeclare the member, you will have a new member. This is called shadowing. See, e.g.
http://www-personal.umich.edu/~saarela/programming/2009/07/c-variable-shadowing.html
http://en.wikipedia.org/wiki/Variable_shadowing
I keep running into the same conundrum over and over again when I try to implement a factory pattern for something like this:
class Base {
template <typename T>
void doSomethingWithMember(T){
}
void doing(){
doSomethingWithMember(this->a);
}
private:
int a;
};
class A: public Base {
double a;
};
class B: public Base{
float a;
};
struct Dictionary {
typedef Base* (*FunctionPointer)(void);
std::map <int, FunctionPointer> fmap;
template <typename Target>
static Base* construct() {
return new Target();
}
Dictionary() {
fmap.insert(std::make_pair(0, &Dictionary::construct<A>));
fmap.insert(std::make_pair(1, &Dictionary::construct<B>));
}
Base* Call( int i ) const {
std::map<int, FunctionPointer>::const_iterator entry = fmap.find( i );
return entry == fmap.end() ? new Base() : (*entry->second)();
}
};
The problem is, I cannot define a in Base because in best case it gets hidden. But without a definition of a i cannot implement a function for the inheritors to cope with their a. What I also tried was implementing Base as a template which led to the problem that I always had to know the returning data type (int, double, float) when creating an object trough the dictionary - saying I had no basic object type for Base<int>, Base<float>, Base<double>. And I do need the dictionary to give me an object according to i without me knowing anything else but i.
Your problem with making Base a template is that you lost your common base. However, you can get that back by making the derived class the template. E.g.:
struct Base {
virtual ~Base() { }
};
template<typename T>
struct Derived : Base {
private:
T a;
};
With the above, you can return a Base * while having your factory construct Derived<X>. Your construct() function would look something like this:
template<typename T>
static Base *construct() {
return new Derived<T>();
}
Any functions that need to manipulate a would be put in Derived<T>, and because Derived is a template, you would only have to implement them once.
I have two user-defined classes:
class A:class Base
{
type x;
doSomething();
}
class B
{
type x;
doSomething();
}
I also have a function which gets a variable of type Base and use dynamic_cast to convert it to type A and use doSomething().
class D : class Base2
{
D(Base _base1):Base2(Base _base1)
{
//here is the actual problem
}
void foo()
{
//b is a private member of class Base2 of type Base
A *a=dynamic_cast(b);
A->doSomething();
}
}
but I want to pass B to this function ,and at the same time I don't want B to inherit from Base.
p.s I don't have access to change Base
how is this possible?
Casting between unrelated classes in not safe. The safest way to achieve what I think you're trying to do is to use a function template:
template <typename T>
void foo(const T& b)
{
b.doSomething();
}