Can't break out of CRTP cyclical reference - c++

I'm trying to structure my program by using CRTP for certain parts to get rid of virtual function call overhead but I'm having trouble with cyclical references between classes.
The program basically has 2 major modes: Hello1 and Hello2 encapsulate this. I'm wondering if perhaps I should just make an enum class Hello { Hello1, Hello2 }; and use that to template everything EXCEPT for the Deriv template type where I need to use concrete classes? I tried searching for this but couldn't seem to find something matching my particular use case (or at least I didn't recognize).
template<typename T>
struct Processor
{
std::vector<T> v_; // holds HelloContainers
void usage1()
{
for (auto& v : v_)
v->doSomethingToHello();
}
void specialize() { /* ... */ }
};
template<> Container<Hello1>::specialize()
{
// something special for Hello1 only!
}
template<typename Deriv2>
struct HelloContainerBase
{
void needsAccessFromHello1And2();
// a whole bunch of other things that Hello{1,2} need access to
// ..
};
template<typename T>
struct HelloContainer : public HelloContainerBase<HelloContainer<T>>
{
void doSomethingToHello() { hello_->func2(); }
void callFunc1() { hello_->func1(); } // <--- slow?
void needsAccessFromHello()
T* hello_; // needs
};
struct HelloBase
{
virtual void func1() = 0;
};
template<typename Deriv>
struct HelloCRTP : public HelloBase
{
void func2()
{
static_cast<Deriv>(this)->func2impl();
}
HelloContainer<Deriv>* proc_;
};
struct Hello1 : public HelloCRTP<Hello1>
{
void func1(); // hopefully no virtual method overhead?
void func2impl(); // no virtual method overhead
// ...
};
struct Hello2 : public HelloCRTP<Hello1>
{
void func1(); // hopefully no virtual method overhead?
void func2impl(); // no virtual method overhead
// ...
};
int main()
{
auto hc1 = new HelloContainer<Hello1>();
auto proc = new Processor<Hello1>
proc.v_.push_back(hc1);
proc.usage();
proc.specialize();
hc1->doSomethingToHello();
}

Related

Trampolines in C++ Metaprogramming

I am reading a book on metaprogramming and there is secession on Trampolines:
struct generic_t
{
void* obj;
void(*del)(void*);
};
template <typename T> // outer template parameter
generic_t copy_to_generic(const T& value)
{
struct local_cast // local class
{
static void destroy(void* p) // void*-based interface
{
delete static_cast<T*>(p); // static type knowledge
}
};
generic_t p;
p.obj = new T(value); // information loss: copy T* to void*
p.del = &local_cast::destroy;
return p;
}
I totally understand how it works but I don't know what is the application of it! and where do you usually use this technique? dose anyone know about it? thanks :)
I use it in many places in my programs. One thing I like with this method is that you can hold a list of unrelated types. For example, I've seen a lot of code that looked like that:
struct Abstract { virtual ~Abstract() = default; };
template<typename P>
struct AbstractHandler : Abstract {
virtual void handle(P) = 0;
};
template<typename P, typename H>
struct Handler : AbstractHandler<P>, private H {
void handle(P p) override {
H::handle(p);
}
};
struct Test1 {};
struct Test1Handler {
void handle(Test1) {}
};
struct Test2 {};
struct Test2Handler {
void handle(Test2) {}
};
int main() {
std::vector<std::unique_ptr<Abstract>> handlers;
handlers.emplace_back(std::make_unique<Handler<Test1, Test1Handler>>());
handlers.emplace_back(std::make_unique<Handler<Test2, Test2Handler>>());
// some code later....
dynamic_cast<AbstractHandler<Test1>*>(handlers[0].get())->handle(Test1{});
dynamic_cast<AbstractHandler<Test2>*>(handlers[1].get())->handle(Test2{});
}
Dynamic casts add unnecessary overhead to the program. Instead, you could use type easure just like the one you've made to avoid this overhead.
Plus, there is no reason for Abstract to even exist. It's an interface that expose no useful function. The real need here is to hold a list of unrelated interfaces.
Let's say we ajust type easure to allow copy_to_generic to cast the instance to a parent class.
template <typename Parent, typename T>
generic_t to_generic(T&& value) // forward is better.
{
struct local_cast
{
static void destroy(void* p)
{
// we cast to the parent first, and then to the real type.
delete static_cast<std::decay_t<T>*>(static_cast<Parent*>(p));
}
};
generic_t p;
p.obj = static_cast<Parent*>(new std::decay_t<T>(std::forward<T>(value)));
p.del = &local_cast::destroy;
return p;
}
Look at this code with the type easure:
// No useless interface
template<typename P>
struct AbstractHandler {
// No virtual destructor needed, generic_t already has a virtual destructor via `del`
virtual void handle(P) = 0;
};
template<typename P, typename H>
struct Handler : private H {
void handle(P p) override {
H::handle(p);
}
};
struct Test1 {};
struct Test1Handler {
void handle(Test1) {}
};
struct Test2 {};
struct Test2Handler {
void handle(Test2) {}
};
int main() {
std::vector<generic_t> handlers;
handlers.emplace_back(
to_generic<AbstractHandler<Test1>>(Handler<Test1, Test1Handler>{})
);
handlers.emplace_back(
to_generic<AbstractHandler<Test2>>(Handler<Test2, Test2Handler>{})
);
// some code later....
static_cast<AbstractHandler<Test1>*>(handlers[0].obj)->handle(Test1{});
static_cast<AbstractHandler<Test2>*>(handlers[1].obj)->handle(Test2{});
}
No empty interface and no dynamic casts anymore! This code does the same thing as the other one, but faster.

In C++ Is there a way for the Child to reuse the the Parent class implementation of the pure virtual function defined in GrandParent

Consider the below code, EventGeneratorBase is a helper class intended to provide the actual implementation for AddEventHandler() and I would like to use that implementation in the class RemoteControl instead of explicity defining it. I know it's not possible to instantiate RemoteControl without defining the method but is there a shortcut or an easy way to avoid manually defining the methods.
Note: The code in it's present form doesn't compile because RemoteControl can't be instantiated.
#include <iostream>
#include <vector>
#include <memory>
template<class TEventHandler> struct IEventGenerator {
virtual ~IEventGenerator() = default;
virtual void AddEventHandler(std::weak_ptr<TEventHandler> eventHandler) = 0;
};
template <class TEvents> struct EventGeneratorBase : IEventGenerator<TEvents> {
void AddEventHandler(std::weak_ptr<TEvents> target) {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
struct IControlEvents {
virtual ~IControlEvents() = default;
virtual void PowerOn() = 0;
virtual void PowerOff() = 0;
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
virtual ~IRemoteControl() = default;
virtual void Toggle() = 0;
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
// I don't want to define AddEventHandler() in this class and
// would like to inherit the implementation from EventGeneratorBase
void Toggle() {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
t->PowerOn();
t->PowerOff();
}
}
}
};
struct Light : IControlEvents {
Light(std::string color) : _color(color) { }
void PowerOn() {
std::cout << _color << "::Light ON!" << std::endl;
}
void PowerOff() {
std::cout << _color << "::Light OFF!" << std::endl;
}
private:
std::string _color;
};
int main() {
std::shared_ptr<IRemoteControl> remote(new RemoteControl); // ERROR: Can't instantiate
std::shared_ptr<IControlEvents> light1(new Light("GREEN"));
std::shared_ptr<IControlEvents> light2(new Light("RED"));
remote->AddEventHandler(light1);
remote->AddEventHandler(light2);
remote->Toggle();
return 0;
}
Your problem is that you have two distinct sub-objects of type IEventGenerator<IControlEvents> within your RemoteControl object. One via EventGeneratorBase<IControlEvents> and one via IRemoteControl.
There are two ways to prevent you from having two distinct subobjects. The first is to inherit virtually from IEventGenerator<TEventHandler> in both spots. This has a modest run-time cost. Simply add virtual before every case of inheritance from IEventGenerator<?> and you are done.
A second method is to note that EventGeneratorBase is intended to help with implementing IEventGenerator.
template<class T> struct tag{using type=T;};
template<class Tag> using type_t=typename Tag::type;
template<class TEventHandler>
tag<TEventHandler> get_event_handler_type(
IEventGenerator<TEventHandler> const*
) { return {}; }
template<class X>
using event_handler_type = type_t< decltype( get_event_handler_type( (X*)nullptr ) ) >;
template <class Base, class TEvents = event_handler_type<Base>>
struct EventGeneratorHelper :
Base
{
void AddEventHandler(std::weak_ptr<TEvents> target) override {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
now, go down to here:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
and change how we inherit. We now interpose EventGeneratorHelper between us and IRemoteControl, so they now share the same common IEventGenerator.
This removes the need for virtual inheritance, but does up your compile time, and can cause some executable code bloat.
We can go a step further. Add this to EventGeneratorHelper:
template<class Action>
void FireEvents( Action&& action ) const {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
action(t);
}
}
}
which reduces RemoteControl to:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
void Toggle() {
this->FireEvents([](std::shared_ptr<IRemoteControl> const& ptr){
t->PowerOn();
t->PowerOff();
});
}
};
which I think is nice -- requiring clients to know the right way of iterating seems silly.
You have a problem in your inheritance hierarchy.
template <class TEvents> struct EventGeneratorBase :IEventGenerator<TEvents> {
[...]
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
[...]
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
[...]
};
This is not doing what you might expect. Instead, your class RemoteControl inherits twice from IEventGenerator, once from IRemoteControl and once from EventGeneratorBase.

c++ design: avoid iterating over types with an existing class hierarchy

Please consider the following (simplified) class hierarchy and processing functions:
struct msgBase
{
virtual int msgType() const=0;
};
struct msgType1:public msgBase
{
virtual int msgType() const{return 1;}
};
struct msgType2:public msgBase
{
virtual int msgType() const {return 2;}
};
void process(const msgType1& mt1)
{
// processing for message type 1
}
void process(const msgType2& mt2)
{
// processing for message type 2
}
void process(const msgBase& mbase)
{
switch(mbase.msgType())
{
case 1:
process(static_cast<const msgType1&>(mbase));
break;
case 2:
process(static_cast<const msgType2&>(mbase));
break;
}
}
In an integrated design, msgBase would be given a virtual "process" method, to avoid needing to iterate over the types.
If it's not possible or desirable to modify any of the classes, are there any alternatives to iterating over the types?
I've experimented with a decorator/factory pattern where a parallel hierarchy of classes encapsulates the given classes, and implements the necessary virtual functions, but this results in an awful lot of boilerplate, and the factory function still needs to iterate over the types!
I could replace the switch statement with a series of dyamic_casts, but that still leaves the same weaknesses.
As requested by Simon, here is what I mean by CRTP:
typedef <class Derived>
struct msgBase
{
virtual void process(){
// redirect the call to the derived class's process()
static_cast<Derived*>(this) -> process();
};
struct msgType1:public msgBase<msgType1>
{
void process(){
// process as per type-1
}
};
struct msgType2:public msgBase<msgType1>
{
void process(){
// process as per type-2
}
};
What's happening here? Consider this case:
msgBase* msg = new msgType1();
msg->process();
normally (without CRTP) this would only call msgBase::process(). But now, msgBase "knows" about msgType1 using the template, so it is redirected to msgType1::process at compile time.
Something like this could work:
These classes are used to do the casting automatically:
struct dispatcher_base {
virtual void process(const msgBase&) = 0;
};
template <class T>
struct dispatcher_impl : dispatcher_base {
void process(const msgBase& b) override {
::process(static_cast<const T&>(b));
}
};
We'll store them in a map:
auto g_table = std::map<int, std::unique_ptr<dispatcher_base>>{};
But now you have to initialize this table somewhere:
template <class T>
void register_msg() {
g_table[T{}.msgType()].reset(new dispatcher_impl<T>{});
}
...
register_msg<msgType1>();
register_msg<msgType2>();
You can add an assert to register_msg to make sure that msgTypes are unique.
Your process function will look like this:
void process(const msgBase& b) {
assert(g_table.find(b.msgType()) != g_table.end());
g_table[b.msgType()]->process(b);
}
You can replace assert with any other logic of course.
If you can't modify the classes then you can use decorators to get polymorphic type deduction.
struct DecorBase {
DecorBase(msgBase& b) : b_(b) {}
virtual ~DecorBase() {}
virtual void process() = 0;
msgBase& b_;
};
struct DecorType1 : public DecorBase {
DecorType1(msgType1& t1) : DecorBase(t1) {}
void process() override {
std::cout << "Processing Type 1" << std::endl;
}
};
struct DecorType2 : public DecorBase {
DecorType2(msgType2& t2) : DecorBase(t2) {}
void process() override {
std::cout << "Processing Type 2" << std::endl;
}
};
And use it like this:
msgType1 t1;
msgType2 t2;
DecorType1 dt1(t1); // Wrap objects in respective decorator.
DecorType2 dt2(t2);
DecorBase& base = dt2;
base.process(); // Uses polymorphism to call function in derived type.
This will require you to write a decorator for every derived type but at least you don't have to iterate over all types during the function call.

Refer to derivative function

I have a base class and a few derivative. I have to 'register' some static function from each of them. Here is the example:
class Base
{
// Some interface...
};
class Der1 : Base
{
static void Do();
};
class Der2 : Base
{
static void Do();
};
void processStatic()
{
SomeFunc(Der1::Do);
SomeFunc(Der2::Do);
}
As you see, SomeFunc receives function pointer. I want to do that automatically with each new derivative class, is it possible? Maybe, predefine static function in Base class and register it there. But I think it's impossible, yes?
Maybe, this will be more easier to understand what do I want:
class Der1 : Base
{
Der1() { SomeFunc(Der1::Do); }
static void Do();
};
class Der2 : Base
{
Der2() { SomeFunc(Der2::Do); }
static void Do();
};
EDIT: Completely replacing previous answer due to clarified requirements.
You could use the CRTP to declare a specialized base class that does nothing more than call your registration function:
#include <iostream>
void SomeFunc(void(*fp)()) {
(*fp)();
};
template <class D>
struct ExtraBass {
ExtraBass() {
static bool once;
if(!once)
SomeFunc(D::Do);
once = true;
}
};
struct Bass {
};
struct Drive : Bass, ExtraBass<Drive> {
static void Do() { std::cout << "Drive::Do\n"; }
};
struct Deride : Bass , ExtraBass<Deride> {
static void Do() { std::cout << "Deride::Do\n"; }
};
int main() {
Drive d1;
Deride d2;
Deride d3;
}
This is not an easy thing to do in C++, but I'm not saying it's impossible. If all you need is a list of subclass names, these answers might help:
Somehow register my classes in a list
c++ List of classes without initializing them for use of static functions
Seems either macro magic or boost mpl is your tool of choice.
I just wondering, if you did something like
void SomeFunc(void (*doFunc)())
{
doFunc();
}
template <class T> int Register()
{
SomeFunc(T::Do);
return 0;
}
template <class T> class Base
{
static int _i;
};
template <class T> int Base<T>::_i = Register<T>();
class Derived : Base<Derived>
{
public:
static void Do() { }
};

Protected External Resource Usage

I'm working with some code where I have the following setup.
struct data
{
void change_safe_member(){}
void read_data(){}
void change_unsafe_member(){}
};
struct data_processor
{
std::shared_ptr<data> get_data(){}
void return_data(std::shared_ptr<data> my_data)
{
my_data->change_unsafe_member(); // ONLY data_processor should call this function.
}
};
struct client
{
void foo(std::shared_ptr<data_processor>& my_processor)
{
auto my_data = my_processor->get_data();
my_data->change_safe_member();
//my_data->change_unsafe_member(); SHOULD NOT BE POSSIBLE TO CALL
my_processor->return_data(my_data);
}
};
The change_unsafe_member should only be used internally by the processor so I would like to hide it or disable it for the client. But I don't know of any nice ways of doing this without resorting to ugly casts...
struct internal_data
{
void change_unsafe_member(){}
};
struct data : public internal_data
{
void change_safe_member(){}
void read_data(){}
};
struct data_processor
{
std::shared_ptr<data> get_data(){}
void return_data(std::shared_ptr<data> my_data)
{
auto internal_data = std::static_pointer_cast<internal_data>(my_data);
internal_data->change_unsafe_member();
}
};
Anyone know of a good pattern to use in situations like this? Maybe visitor pattern or something similar?
EDIT:
As pointed out in the comments one could declare friend classes, there is however one problem... the following will not work.
struct data
{
void change_safe_member(){}
void read_data(){}
private:
friend class data_processor;
virtual void change_unsafe_member(){}
};
struct data_decorator : public data
{
data_decorator(const std::shared_ptr<data>& decoratee) : decoratee_(decoratee){}
void change_safe_member(){decoratee_->change_safe_member();}
void read_data(){decoratee_->read_data();}
private:
virtual void change_unsafe_member()
{
std::cout << "Hello!"; // Add functionality
decoratee_->change_unsafe_member(); // Won't work... compiler error
}
std::shared_ptr<data> decoratee_;
};
// Another example
struct data_group_decorator : public data
{
data_group_decorator (const std::vector<std::shared_ptr<data>>& decoratees) : decoratees_(decoratees){}
void change_safe_member(){decoratee_->change_safe_member();}
void read_data(){decoratee_->read_data();}
private:
virtual void change_unsafe_member()
{
for(size_t n = 0; n < decoratees_.size(); ++n)
decoratees_[n]->change_unsafe_member(); // Won't work... compiler error
}
std::vector<std::shared_ptr<data>> decoratees_;;
};
You can make this happen with inheritance.
struct Y;
struct X {
friend struct Y;
private:
change_unsafe_member() {}
};
struct Y {
protected:
change_unsafe_member(X& x) { x.change_unsafe_member(); }
};
struct some_other : Y {
X x;
change_safe_member() { change_unsafe_member(x); }
};
Any class that inherits from Y can gain X's friendship for any functions that Y defines as effectively forwards from X.
Your last example looks like what you're really asking for is inherited friendship; i.e. you want to have a hierarchy of decorator - derived classes which are all allowed to call the private member function in data. That's answered (with "generally no") elsewhere:
Why does C++ not allow inherited friendship?
Polymorphism might provide some relief in your specific scenario, make class data_decorator an "almost pure" virtual base class, with the only nonvirtual member being a protected change_unsafe_member(), and make that in turn a friend of class data. All decorators would inherit from data_decorator, and call its protected nonvirtual member.