I have a problem with some refactoring I am attempting. We have a lot of code duplication and I am trying to sort this out. I have the following class structure
IMessageSink.h:
class IMessageSink
{
public:
virtual ~IMessageSink() { };
virtual void process(const taurus::Msg& msg) = 0;
};
I have the following base class ModelBase.h which all models must inherit from, at this point please not the use of the friend class EM:
class ModelBase : public virtual IMessageSink
{
public:
ModelBase(Tag a);
void process(const taurus::Msg& msg);
void reset();
private:
friend class EM; // I will ask about this below.
virtual void calculate(double lambda) = 0;
};
The implementation of friend EM is not correct and I ask about this below. I then have a class that implements/inherits from ModelBase, ModelM0.h:
class ModelM0 : public virtual ModelBase
{
public:
ModelM0(Tag a);
static ModelM0* ModelM0::make(Tag a)
{
ModelM0* m = new ModelM0(a);
m->reset();
return m;
}
private:
void calculate(double lambda);
};
with ModelM0.cpp implemented as:
ModelM0::ModelM0(Tag a) : ModelBase(a) { }
void ModelM0::calculate(double lambda)
{
// Do stuff.
}
The problem is with the EM friend class and how to implement this in a generic fashion. Previously, this class only worked with types ModelM0 which did not inherit from ModelBase. Now other models also inherit from ModelBase and EM needs to work with these as well - here lies the problem. I have the following definition in EM.h (which I have changed to a template so we can specify the type of ModelBase we are using TModel):
with EM.h as:
template <class TModel>
class EM : public virtual IMessageSink
{
public:
static EM* make(Tag a)
{
return new EM(a);
}
EM(Tag a);
~EM();
void process(const taurus::Msg& msg);
void run();
private:
struct Bucket
{
TModel* _model;
std::vector<TinyMatrix<1, 1> > _obs
};
EM::Bucket& getModel(int ag);
}
The problem implementation is EM::Bucket& getModel(int ag);, in EM.cpp we have
template<class TModel>
EM<TModel>::EM(Tag a) { }
template<class TModel>
EM<TModel>::~EM()
{
run();
}
template<class TModel>
void EM<TModel>::process(const taurus::Msg& msg)
{
int ag = getMessageCount(msg.type()); // External call.
if (ag <= 3)
{
Bucket& b = getModel(ag);
TModel* m = b._model;
m->process(msg);
}
}
The above seems to be okay, my problem is the implementation of getModel
template<class TModel>
EM<TModel>::Bucket& EM<TModel>::getModel(int ag)
{
// This is not right.
TModel* m;
m = TModel::make(getTag(ag)); // This is not right - I need a factory.
// ... Do stuff.
Bucket& b = // Get a bucket.
b._model = m;
return b;
}
My questions:
How can I change the above code so that in EM<TModel>::getModel(int ag) I can create the correct TModel using make in the above - do I need a factory and how would this be implemented?
In ModelBase.h the EM class is specified as a friend class. How can this me made generic to work with the TModel (ModelBase) type being used?
It is important to note here that this is a refactoring question, not whether-or-not the code I have shown in the methods is proper or correct (this has been cut down in order to succinctly highlight my problems). The refactoring is the only thing I would like help with. Thanks very much for your time.
When I tried to get your code compiling, I had to fix a few missing semicolons and missing types (Tag, taurus::Msg, TinyMatrix) and also fix the declaration and definition of getModel(int ag)
Generally, you need to indicate to the compiler, that Bucket is actually a type name and not some other sort of parameter.
For the declaration you have 2 options:
Bucket& getModel(int ag); // (1)
typename EM<TModel>::Bucket& getModel(int ag); // (2)
(1) is implicit usage of the Bucket type of your current template specialization. (2) is explicit type usage together with the typename keyword for the compiler, as mentioned above.
For the definition, you definitely need to typename keyword, since you are out of your class definition context.
template<class TModel>
typename EM<TModel>::Bucket& EM<TModel>::getModel(int ag)
{
// This is not right.
TModel* m;
m = TModel::make(getTag(ag)); // This is not right - I need a factory.
// ... Do stuff.
Bucket& b = // Get a bucket.
b._model = m;
return b;
}
Just ignore the "This is not right." comments - I copied them over from your sample code. Its actually perfectly right.
For the friend declaration, you need to add a template version, since you want to befriend all possible template instantiations. I looked it up from this answer (Credits to Anycorn)
template <class> friend class EM;
Hope that solves all your issues. Note I used template <class> since you used it. Personally I prefer template <typename>.
Related
I am just thinking about a way to check an object to be valid in a automated way.
I have a couple of hardware related objects (like class A), which can be deleted by external (physical) events.
To detect this I have used shared/weak pointer. But now I am struggling with the checking of the weak pointer. Since this is done in the same way for each member function for many objects, I am currently searching for a way to do this with less redundant code.
In addition I am writing a library and do not want the user to handle this (simply return the weak pointer to the user to handle it by himself is therefor no option)
My best guess is shown below. My problem is, I could not find a way to generate the member functions (func1, and many more ...) automatically within the template. Doing it by myself would result in lot of redundant code for every member function to be validated (and there are a lot)
Each member function of A (and many more other objects) shall be wrapped by a function doing the validation shown below. This is same for all member functions and done for many classes which can be used as type for the Validator.
Does anyone has an idea how to solve this? Maybe there are other (better) ways to solve this.
Many thanks for your help.
Some constraints:
Only C++11 possible,
No exceptions
class A {
public:
void func1() {}
//many more functions
};
template<typename T>
class Validator
{
//has to be done for all functions of A
void func1()
{
if (!wptr.expired())
{
wptr.lock()->func1();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
I would protect the full user function call:
class A {
public:
void func1() {}
//many more functions
};
template <typename T>
class Validator
{
public:
#if 1 // template way, but no-expressive signature
template <typename F>
void do_job(F f)
#else // type-erasure way, expressive, but with some overhead
void do_job(std::function<void (T&)> f)
#endif
{
auto t = wptr.lock();
if (t) {
f(*t);
} else {
errorHandling();
}
}
private:
void errorHandling();
private:
std::weak_ptr<T> wptr;
};
So user might chain call:
Validator<A> val;
val.do_job([](A& a)
{
a.func1();
a.func2();
});
If the caller can live with clunky syntax you can use member function pointers:
#include <memory>
#include <iostream>
class A {
public:
void func1() {
std::cout << "hello func1\n";
}
};
template<typename T>
class Validator
{
public:
Validator(std::shared_ptr<T> p) : wptr(p) {}
template <typename MemFun>
void call(MemFun mf) {
if (!wptr.expired())
{
(wptr.lock().get()->*mf)();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
int main() {
auto x = std::make_shared<A>();
Validator<A> v{x};
v.call(&A::func1);
}
Assume I have a some classes architecture (the number of the classes is growing up during the development time), that each class inherit from N classes with the same basic interface. What is the best way (if possible) to create a base function (in the base class OR in the derived class) that will iterate over the inheritances?
Target: Avoid developers mistakes and make sure we won't forget to call all the base functions from all of the inheritances & make the code more clear to read and understandable.
Please see edit notes for updated state
Short Example:
class shared_base {
public:
virtual void func() = 0;
}
class base_1 : virtual public shared_base {
public:
void func() override {}
}
class base_2 : virtual public shared_base {
public:
void func() override {}
}
class target : virtual public base_1, virtual public base_2 {
public:
void func() override {
// Instead of:
base_1::func();
base_2::func();
// ... My func() implementation
/*
~~TODO~~
for_each(std::begin(inheritances), std::end(inheritances), [](auto& inheritance) -> void { inheritance::func(); })
~~TODO~~
*/
}
}
More descriptive & practical example:
class base {
public:
virtual void func() = 0;
/*...Some interface (pure virtual) functions...*/
}
class base_core : virtual public base {
public:
void func() override {}
/*...Some base implementations for the rest...*/
protected:
template <typename FuncT>
virtual void iterate_over_base_core_inheritances(FuncT function_to_apply) {
/*~~TODO~~*/
}
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_1 : virtual public Decorator {
public:
void func() override {
// Will iterate (once) over Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
}
/*More functions implementations*/
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_2 : virtual public core_1<>, virtual public Decorator {
public:
void func() override {
// Will iterate (twice) over core_1 and Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
core_1::func();
//... Self func() implementation
}
/*More functions implementations*/
protected:
// If it's not possible doing it in the upper hierarchy level is it possible do it here?
template <typename FuncT>
void iterate_over_base_core_inheritances(FuncT function_to_apply) override {
/*~~TODO~~*/
}
}
Some things to know:
I am working on Linux 64x platform (Ubuntu 16.04)- if it's matter for the answers.
The idea behind this code is to create kind of Decorator DP, which will be easy to extend and to understand, and also will enable the developers to use the protected functions/attributes of the base class.
A practical example (for my actual use) can be found in this commit.
Edit:
Thanks to #RaymondChen I got a working solution, with (so far) only one minor issue: Every time I want to use a class that implemented this way, I need to specify the core_base class in it's template arguments list (before- I was using the default type parameter). I am looking for a way to solve this issue.
The current solution:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
Creating an instance example:
Current:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Desired:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
A practical example (for my actual use) can be found in this commit.
Thanks to #RaymondChen I got really close to my original target with the following solution [See update section at the bottom]:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
Explanation:
Using parameters pack we can create a "list" of classes we inherit from, and using folding expression [c++17] we can implement it in just few lines of code.
Pros compare to my original idea:
The object creation line is more clear and logically now:
Before:std::shared_ptr<base> base = std::make_shared<core_2<core_1<core_3<>>>>();
After:std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Because core_1 & core_3 are independent, but core_2 is using both of them.
No need of new function in the base/derived class, it's just fit within the target line (for example in is_equal function that didn't mention within this post).
Lost functionality:
Template validation of is_base_of (Solved with static_assert & fold expressions).
Default inheritance in case that no inheritance specified is not possible yet (Still trying to solve).
Current:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Desired:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
Update
After a lot of research and tries, I came up with the following solution (improved also with C++20 concepts feature):
template <class T>
concept Decorator = std::is_base_of_v<base_core, T>;
class empty_inheritance {};
template<typename Base = base_core, typename ...Decorators>
struct base_if_not_exists {
static constexpr bool value = sizeof...(Decorators);
using type = typename std::conditional<value, empty_inheritance, Base>::type;
};
template <Decorator ...Decorators>
class core_2 : virtual public base_if_not_exists<base_core, Decorators...>::type, virtual public Decorators... {
public:
void func() override {
if constexpr (!base_if_not_exists<base_core, Decorators...>::value) {
base_core::func();
}
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
No functionality lost :)
My problem with Qt & pimpl is not actually a problem, more a request for best-practice advice.
So: we've got quite a large project with lots of GUI and other Qt classes. Readability of headers is required for fine collaboration, reducing compilation time is also a matter of regular consideration.
Thus, there I have lots of classes like:
class SomeAwesomeClass: public QWidget
{
Q_OBJECT
public:
/**/
//interface goes here
void doSomething();
...
private:
struct SomeAwesomeClassImpl;
QScopedPointer<SomeAwesomeClassImpl> impl;
}
Of course, the Pimpl class is in the .cpp file, works fine, like:
struct MonitorForm::MonitorFormImpl
{
//lots of stuff
}
This piece of software is supposed to be crossplatform (not a surprise) and cross-compiled without significant effort. I know about Q_DECLARE_PRIVATE, Q_D and other macros, they make me think more about Qt MOC, possible differences in Qt versions (because of legacy code), but this way or another there are many lines of code contatinig something like
impl->ui->component->doStuff();
//and
impl->mSomePrivateThing->doOtherStuff()
//and even
impl->ui->component->SetSomething(impl->mSomePrivateThing->getValue());
The pseudo-code above is a much simplified version of the real one, but most of us are fine with it. But some colleagues insist, that it's rather bothering to write and read all those long lines, especially when impl->ui->mSomething-> is repeating too often. The opinion states, that Qt marcos also add visual garbaging to the situation in the end. Seversl #define's could help, but those are considered generally bad practice.
In short, based on your experience, is there a way to make pimpl usage more laconic? Maybe it isn't truly required as often as seems, in non-library classes for example? Maybe the goals of it's usage are not equal, depending on circumstances?
What's the proper way to cook it, anyway?
Introduction
I know about Q_DECLARE_PRIVATE, Q_D and other macros
You know about them, but have you actually used them and understand their purpose, and - for the most part - their inevitability? Those macros weren't added to make stuff verbose. They are there because you end up needing them.
There are no differences in Qt PIMPL implementation between Qt versions, but you are depending on Qt's implementation details when you inherit from QClassPrivate, should you do so. The PIMPL macros have nothing to do with moc. You can use them in plain C++ code that doesn't use any Qt classes at all.
Alas, there's no escaping what you want for as long as you implement the PIMPLs the usual way (which is also Qt way).
Pimpl-pointer vs this
First of all, let's observe that impl stands for this, but the language lets you skip using this-> in most cases. Thus, it's nothing too foreign.
class MyClassNoPimpl {
int foo;
public:
void setFoo(int s) { this->foo = s; }
};
class MyClass {
struct MyClassPrivate;
QScopedPointer<MyClassPrivate> const d;
public:
void setFoo(int s);
...
virtual ~MyClass();
};
void MyClass::setFoo(int s) { d->foo = s; }
Inheritance demands...
Things become generally outlandish when you have inheritance, though:
class MyDerived : public MyClass {
class MyDerivedPrivate;
QScopedPointer<MyDerivedPrivate> const d;
public:
void SetBar(int s);
};
void MyDerived::setFooBar(int f, int b) {
MyClass::d->foo = f;
d->bar = b;
}
You'll want to re-use a single d-pointer in the base class, but it will have the wrong type in all derived classes. Thus you might think of casting it - that's even more boilerplate! Instead, you use a private function that returns a correctly-cast d-pointer. Now you need to derive both public and private classes, and you need private headers for the private classes, so that the derived classes can use them. Oh, and you need to pass the pointer to the derived pimpl to the base class - because that's the only way you can initialize the d_ptr while keeping it const, as it must be. See - Qt's PIMPL implementation is verbose because you do actually need all of it to write safe, composable, maintainable code. No way around it.
MyClass1.h
class MyClass1 {
protected:
struct Private;
QScopedPointer<Private> const d_ptr;
MyClass1(Private &); // a signature that won't clash with anything else
private:
inline Private *d() { return (Private*)d_ptr; }
inline const Private *d() const { return (const Private*)d_ptr; }
public:
MyClass1();
virtual ~MyClass1();
void setFoo(int);
};
MyClass1_p.h
struct MyClass1::Private {
int foo;
};
MyClass1.cpp
#include "MyClass1.h"
#include "MyClass1_p.h"
MyClass1::MyClass1(Private &p) : d_ptr(&p) {}
MyClass1::MyClass1() : d_ptr(new Private) {}
MyClass1::~MyClass1() {} // compiler-generated
void MyClass1::setFoo(int f) {
d()->foo = f;
}
MyClass2.h
#include "MyClass1.h"
class MyClass2 : public MyClass1 {
protected:
struct Private;
private:
inline Private *d() { return (Private*)d_ptr; }
inline const Private *d() { return (const Private*)d_ptr; }
public:
MyClass2();
~MyClass2() override; // Override ensures that the base had a virtual destructor.
// The virtual keyword is not used per DRY: override implies it.
void setFooBar(int, int);
};
MyClass2_p.h
#include "MyClass1_p.h"
struct MyClass2::Private : MyClass1::Private {
int bar;
};
MyClass2.cpp
MyClass2::MyClass2() : MyClass1(*new Private) {}
MyClass2::~MyClass2() {}
void MyClass2::setFooBar(int f, int b) {
d()->foo = f;
d()->bar = b;
}
Inheritance, Qt way
Qt's PIMPL macros take care of implementing d() functions. Well, they implement d_func() and then you use the Q_D macro to obtain a local variable that is simply d. Rewriting the above:
MyClass1.h
class MyClass1Private;
class MyClass1 {
Q_DECLARE_PRIVATE(MyClass1)
protected:
QScopedPointer<Private> d_ptr;
MyClass1(MyClass1Private &);
public:
MyClass1();
virtual ~MyClass1();
void setFoo(int);
};
MyClass1_p.h
struct MyClass1Private {
int foo;
};
MyClass1.cpp
#include "MyClass1.h"
#include "MyClass1_p.h"
MyClass1::MyClass1(MyClass1Private &d) : d_ptr(*d) {}
MyClass1::MyClass1() : d_ptr(new MyClass1Private) {}
MyClass1::MyClass1() {}
void MyClass1::setFoo(int f) {
Q_D(MyClass1);
d->foo = f;
}
MyClass2.h
#include "MyClass1.h"
class MyClass2Private;
class MyClass2 : public MyClass1 {
Q_DECLARE_PRIVATE(MyClass2)
public:
MyClass2();
~MyClass2() override;
void setFooBar(int, int);
};
MyClass2_p.h
#include "MyClass1_p.h"
struct MyClass2Private : MyClass1Private {
int bar;
};
MyClass2.cpp
MyClass2() : MyClass1(*new MyClass2Private) {}
MyClass2::~MyClass2() {}
void MyClass2::setFooBar(int f, int b) {
Q_D(MyClass2);
d->foo = f;
d->bar = b;
}
Factories simplify pimpl
For class hierarchies that are sealed (i.e. where the user doesn't derive), the interface can be sanitized from any private details whatsoever by the use of factories:
Interfaces
class MyClass1 {
public:
static MyClass1 *make();
virtual ~MyClass1() {}
void setFoo(int);
};
class MyClass2 : public MyClass1 {
public:
static MyClass2 *make();
void setFooBar(int, int);
};
class MyClass3 : public MyClass2 {
public:
static MyClass3 *make();
void setFooBarBaz(int, int, int);
};
Implementations
template <class R, class C1, class C2, class ...Args, class ...Args2>
R impl(C1 *c, R (C2::*m)(Args...args), Args2 &&...args) {
return (*static_cast<C2*>(c).*m)(std::forward<Args2>(args)...);
}
struct MyClass1Impl {
int foo;
};
struct MyClass2Impl : MyClass1Impl {
int bar;
};
struct MyClass3Impl : MyClass2Impl {
int baz;
};
struct MyClass1X : MyClass1, MyClass1Impl {
void setFoo(int f) { foo = f; }
};
struct MyClass2X : MyClass2, MyClass2Impl {
void setFooBar(int f, int b) { foo = f; bar = b; }
};
struct MyClass3X : MyClass3, MyClass3Impl {
void setFooBarBaz(int f, int b, int z) { foo = f; bar = b; baz = z;}
};
MyClass1 *MyClass1::make() { return new MyClass1X; }
MyClass2 *MyClass2::make() { return new MyClass2X; }
MyClass3 *MyClass3::make() { return new MyClass3X; }
void MyClass1::setFoo(int f) { impl(this, &MyClass1X::setFoo, f); }
void MyClass2::setFooBar(int f, int b) { impl(this, &MyClass2X::setFooBar, f, b); }
void MyClass3::setFooBarBaz(int f, int b, int z) { impl(this, &MyClass3X::setFooBarBaz, f, b, z); }
This is very basic sketch that should be further refined.
#KubaOber gave an excellent coverage of how pimpl works and how to implement it. One thing not covered that you discussed are the inevitable macros to simplify the boilerplate. Let's take a look at a possible implementation, borrowed from my own Swiss Army knife library, which is clearly based on Qt's take.
Firstly, we need a base public interface and a base private implementation with the boilerplate. Inheriting directly from Qt's implementation is useless if we aren't using Qt (and an incredibly bad idea besides), so we'll just create a lightweight base class for the implementation (or d_ptr) and the implementation's back-pointer to the interface (the q_ptr).
#include <QScopedPointer> //this could just as easily be std::unique_ptr
class PublicBase; //note the forward declaration
class PrivateBase
{
public:
//Constructs a new `PrivateBase` instance with qq as the back-pointer.
explicit PrivateBase(PublicBase *qq);
//We declare deleted all other constructors
PrivateBase(const PrivateBase &) = delete;
PrivateBase(PrivateBase &&) = delete;
PrivateBase() = delete;
//! Virtual destructor to prevent slicing.
virtual ~PrivateBase() {}
//...And delete assignment operators, too
void operator =(const PrivateBase &) = delete;
void operator =(PrivateBase &&) = delete;
protected:
PublicBase *qe_ptr;
};
class PublicBase
{
public:
//! The only functional constructor. Note that this takes a reference, i.e. it cannot be null.
explicit PublicBase(PrivateBase &dd);
protected:
QScopedPointer<PrivateBase> qed_ptr;
};
//...elsewhere
PrivateBase::PrivateBase(PublicBase *qq)
: qe_ptr(qq)
{
}
PublicBase::PublicBase(PrivateBase &dd)
: qed_ptr(&dd) //note that we take the address here to convert to a pointer
{
}
Now to the macros.
/* Use this as you would the Q_DECLARE_PUBLIC macro. */
#define QE_DECLARE_PUBLIC(Classname) \
inline Classname *qe_q_func() noexcept { return static_cast<Classname *>(qe_ptr); } \
inline const Classname* qe_cq_func() const noexcept { return static_cast<const Classname *>(qe_ptr); } \
friend class Classname;
/* Use this as you would the Q_DECLARE_PRIVATE macro. */
#define QE_DECLARE_PRIVATE(Classname) \
inline Classname##Private* qe_d_func() noexcept { return reinterpret_cast<Classname##Private *>(qed_ptr.data()); } \
inline const Classname##Private* qe_cd_func() const noexcept { return reinterpret_cast<const Classname##Private *>(qed_ptr.data()); } \
friend class Classname##Private;
These are fairly self-explanatory: they cast the stored pointer to the appropriate derived type. The macro leverages the class name + "Private" to cast to the right type. This means your private class MUST follow the naming pattern: InterfaceClass becomes InterfaceClassPrivate. For scope resolution to work, they need to be in the same namespace, too. Your private class can't be a member of your public class.
And finally, the accessors, with a C++11 twist:
#define QE_DPTR auto d = qe_d_func()
#define QE_CONST_DPTR auto d = qe_cd_func()
#define QE_QPTR auto q = qe_q_func()
#define QE_CONST_QPTR auto q = qe_cq_func()
Not having to explicitly specify the class name makes usage incredibly easy and less rigid. Should this class be renamed or the function moved to another level in the inheritance hierarchy, you don't have to change the QE_CONST_DPTR statement.
SomeInterface::getFoo() const noexcept
{
QE_CONST_DPTR;
return d->foo;
}
would become:
SomeInterfaceInheritingFromSomeOtherInterface::getFoo() const noexcept
{
QE_CONST_DPTR;
return d->foo;
}
One purpose of PIMPL is to decouple interface from private implementation. Examples like impl->ui->component->doStuff(); are a sign that there is a problem with the scope of the interface. IMHO you should normally not see more than one deep calls.
I.e.
impl->doStuff(); OK
impl->ui->doStuff(); Hmmm, better avoid that.
impl->ui->component->... Uh oh, things go wrong here. Caller needs to know far too much details of the implementation. That's not the purpose of PIMPL!
You may want to read https://herbsutter.com/gotw/_100/, especially the section What parts of the class should go into the impl object?
I want to implement a class hierarchy for object dispatching. Different classes dispatch different elements, and each class can dispatch its element represented as different data types.
It is better understood through a (faulty) example. This is what I would like to have if virtual function templating was allowed:
class Dispatcher {
template <class ReturnType>
virtual ReturnType getStuffAs();
};
So that I can implement subclasses as:
class CakeDispatcher : public Dispatcher {
template <>
virtual Recipe getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
};
class DonutDispatcher : public Dispatcher {
template <>
virtual Frozen getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
}
So that I can do the following later on:
void function( Dispatcher * disp ) {
// Works for Donut and Cake, but result will be a different Baked object
Baked b = disp->getStuffAs<Baked>();
// works if disp points to a DonutDispatcher
// fails if it is a CakeDispatcher
// can be compiling/linking time error or runtime error. I don't care
Frozen f = disp->getStuffAs<Frozen>();
}
Requirements/constraints:
All possible return types are not known beforehand. That's why I "need" templates.
Each class can provide just some return types.
Classes must have a common ancestor, so that I can store objects through a pointer to parent class and invoke functions through this pointer.
EDIT: I CAN'T use C++11 features, but I CAN use boost library.
Things I've thought about, but are not a solution:
Obviously, virtual template functions
Curiously Recurring Template Pattern: breaks the condition of common ancestor
Using some kind of traits class containing the functionality of children classes, but it does not work because a non-virtual implementation in the parent class does not have access to this information
I could maybe store some typeid info in the parent class, passed by children on construction. This makes possible for the non-virtual parent dispatching method to dynamic-cast itself to the children type... but it appears to be ugly as hell, and I don't know if this can cause some kind cycle-referencing problem.
class Dispatcher {
private:
typeid(?) childType;
public:
Dispatcher(typeid childT) : childType(childT) {}
// NOT VIRTUAL
template <class ReturnType>
ReturnType getStuffAs()
{
// or something equivalent to this cast, which I doubt is a correct expression
return dynamic_cast<childType *>(this)->childGetStuffAs<ReturnType>();
}
};
Then child classes would implement childGetStuffAs functions, which are not virtual too.
I've read like 5-10 related questions, but none of the provided solutions seems to fit this problem.
Can any of you come up with a better solution?
Is there a standard pattern/technique for solving this problem?
EDIT: The real problem
In the real problem, I have physical models with properties that can be represented in multiple ways: functions, matrices, probability distributions, polynomials, and some others (for example, a non-linear system can be represented as a function but not as a a matrix, while a linear system can be transformed to both).
There are also algorithms which can use those models indistinctly, but they could require specific representations for some model features. That's the reason for the "getStuffAs" function. The whole think is a bit complicated --too much to explain it here properly--, but I can guarantee that in this context the interface is well defined: input, computation and output.
My intention was to make this possible assuming that the number of possible representations is fully defined beforehand, and making it possible to transform the products to already existing types/classes that cannot be modified.
However, i'm starting to realize that this is, indeed, not possible in a simple way --I don't want to write a library just for this problem.
#include <cstdio>
// as a type identifier
struct stuff {
virtual void foo() {}
};
template <typename T>
struct stuff_inh : stuff {
};
struct Dispatcher {
template <typename T>
T* getStuffAs() {
return (T*)((getStuffAsImpl( new stuff_inh<T>() )));
}
virtual void* getStuffAsImpl(void*) = 0;
virtual void type() {printf("type::dispatcher\n");}
};
struct Cake : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("cake impl\n");
if (dynamic_cast<stuff_inh<Cake>*>(s) == NULL) {
throw "bad cast";
}
return (void*)(new Cake());
}
virtual void type() {printf("type::Cake\n");}
};
struct Rabbit : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("rabbit impl\n");
if (dynamic_cast<stuff_inh<Rabbit>*>(s) != NULL) {
return (void*)(new Rabbit());
}
else if (dynamic_cast<stuff_inh<Cake>*>(s) != NULL) {
return (void*)(new Cake());
}
else {
throw "bad cast";
}
}
virtual void type() {printf("type::Rabbit\n");}
};
void foo(Dispatcher* d) {
d->getStuffAs<Cake>()->type();
d->getStuffAs<Rabbit>()->type();
}
int main() {
Rabbit* r = new Rabbit;
foo(r);
Cake* c = new Cake;
foo(c);
}
I an not sure about the correctness of this ugly solution, may it be helpful for you. >_<
deletion of resource is not coded for a clearer look.
My solution is a combination of recurring template and diamond inheritance.
At least it's working. :)
#include <iostream>
class Dispatcher
{
public:
template<class T>
T getStuff()
{
return T();
}
};
template<class T>
class Stuffer : public Dispatcher
{
public:
template<class TT=T>
TT getStuff(){
return reinterpret_cast<TT>(this);
}
};
class Cake{
public:
Cake(){}
void print()
{
std::cout << "Cake" << std::endl;
}
};
class Recipe
{
public:
Recipe(){}
void print()
{
std::cout << "Recipe" << std::endl;
}
};
class CakeRecipe : public Stuffer<Cake>, public Stuffer< Recipe >
{
public:
};
int main()
{
Dispatcher* cr = reinterpret_cast<Dispatcher*>(new CakeRecipe());
cr->getStuff<Cake>().print();
cr->getStuff<Recipe>().print();
getchar();
return 1;
}
Right now, I'm writing a program on a feature-based approach. Every functionality besides the bare skeleton comes as its own package, derived from a feature class.
I have the Following Header definition:
class Feature
{
public:
Feature(std::string Name)
: Parent(nullptr), Name(Name)
{
if (FeatureNames.count(Name) == 0)
FeatureNames.insert(Name);
else
throw std::logic_error(std::string("Feature: The Feature with the name '") + Name + "' already exists");
}
virtual ~Feature(){}
const std::string &getName(){ return Name; }
virtual void shutDown() = 0;
protected:
Feature *Parent;
private:
static std::set<std::string> FeatureNames;
std::string Name;
};
template<class ChildFeat>
class FeatureEx : public Feature
{
public:
FeatureEx(std::string Name) :Feature(Name){}
virtual ~FeatureEx(){}
void addChildFeature(ChildFeat *Child);
protected:
std::vector<ChildFeat*> Children;
};
//implementation
template<class ChildFeat>
void FeatureEx<ChildFeat>::addChildFeature(ChildFeat *child)
{
Children.push_back(child);
child->Parent = this;
}
And I have a Feat-class and a ChildFeat-Class, like the following:
class FeatureClass : public FeatureEx<MyChildFeatureInterface>
{
...
}
class MyChildFeat : public Feature, public MyChildFeatureInterface
{
...
}
When I now try to call the addChildFeature() method on an Instance of FeatureClass
the compiler is crying, because the addChildFeat() method only sees a MyChildFeatureInterface, which of course does not have the member Parent.
I could easily bypass this problem by deriving MyChildFeatureInterface directly from Feature, but on the one hand I find that sub-optimal and on the other hand I was wondering whether there is a way to tell the Compiler: "This template Argument, can be any class, BUT IT MUST BE DERIVED from class X".
Sure, you can easily say to the compiler that a class must be derived from Base.
An example with a function:
template<class X> auto my_function1(X&& x)
-> decltype(*declval<const volatile Base**>() = &x, declval<void>());
If x is not a kind of Base, so does not derive from it, the assignment is ill-formed and thus the function is removed from consideration at the overload-resolution step.
I like this form, because it is immediately transferable to checking any odd expressions you might want.
Or using the pre-packaged tests from the standard-library as Matthieu M. rightly mentions in a comment (only work on classes):
template<class X> auto my_function2(X&& x)
-> enable_if_t<is_base_of<Base, typename decay<X>::type>::value, void>;