Runtime type deduction and code duplication - c++

I have some types defined by the values of an enumerator, which represent the type of data read in from a file. I wish to do a different processing workflow based on the type of data , but it results in a lot of code duplication:
#include <iostream>
enum dataType {
type1,
type2,
type3
};
struct File {
File(dataType type):type{type}{};
dataType type;
};
void process_file(File file)
{
if(file.type == dataType::type1){ std::cout << "Do work A" << std::endl; };
if(file.type == dataType::type2){ std::cout << "Do work B" << std::endl; };
if(file.type == dataType::type3){ std::cout << "Do work C" << std::endl; };
}
int main(){
File file(dataType::type2);
process_file(file);
return 0;
}
My main problem is with having to check the value via "if" or a switch statement. Imagine there being 50 types instead of just 3 and it becomes quite a chore and error prone to check every single one.
Does anyone know of a way to deal with this? Template code is the obvious thing to try but I'm stuck using the enumerator to determine the type, so I didn't think template code was possible here, at least the attempts I've made have not been successful.

A typical way to get rid of switch is inheritance and virtual function:
struct File {
virtual ~File() = default;
virtual void process() = 0;
};
struct Type1File : public File {
void process() override { std::cout << "Do work A" << std::endl; };
};
struct Type2File : public File {
void process() override { std::cout << "Do work B" << std::endl; };
};
int main(){
std::unique_ptr<File> file = std::make_unique<Type1File>();
file->process();
return 0;
}

How about injecting a SomeWorker object into the file class instead of having a type data member?
class SomeWorker
{
...
public:
virtual void DoWork() = 0;
};
class SomeWorker1 : public SomeWorker
{
...
public:
void DoWork() override { std::cout << "Do work A" << std::endl;}
};
class SomeWorker2 : public SomeWorker
{
...
public:
void DoWork() override { std::cout << "Do work B" << std::endl;}
};
...
struct File {
File(SomeWorker worker):someWorker{worker}{};
SomeWorker someWorker;
};
int main(){
SomeWorker2 someWorker;
File file(someWorker);
file.someWorker.DoWork();
return 0;
}
Obviously, the code is not complete and there are virtual destructors to add and things to improve, but you get the idea...

You can do it passing the dataType as a template parameter.
#include <iostream>
enum class dataType {
type1,
type2,
type3
};
template <dataType T>
struct File {};
void process_file(File<dataType::type1> file) {
std::cout << "Do work A" << std::endl;
}
void process_file(File<dataType::type2> file) {
std::cout << "Do work B" << std::endl;
}
void process_file(File<dataType::type3> file) {
std::cout << "Do work C" << std::endl;
}
int main() {
File<dataType::type1> file1;
File<dataType::type2> file2;
File<dataType::type3> file3;
process_file(file1);
process_file(file2);
process_file(file3);
return 0;
}
However you then also need to accommodate the fact that File is a template, so passing it to other functions ect. is not as easy anymore. You can either change all functions dealing with File to a template aswell, or give all the File variations a common base class.
The other answers seem easier and more to the point in this case to me. Mostly posted this since you mentioned it in your question.

Related

Any techniques or tricks to modifying existing functions in C++?

Within JavaScript, you can pull off something like this:
function bunny() { alert("The bunny jumped."); }
var oldBunny = bunny;
function bunny() {
oldBunny();
alert("The bunny also ran.");
}
bunny(); // The bunny Jumped. The bunny also ran.
As one can see, the old "bunny" function had code appended to it by copying to a variable, then recreating the function with the same name. The copy of the original function runs, and the new code also runs.
I wish to replicate a similar mechanic in C++.
Now before you have a meltdown and start explaining the differences between static and dynamic languages, I get it. I'm not looking for something identical to what's provided, but I do desire something similar.
Furthermore, I'm not trying to do this to modify existing code; I wish to format my own source code to allow such a mechanic for other users to take advantage of.
One of the first ideas I had was to perhaps setup various macros within the code that could later be modified by other files.
Another idea would be to create a Signal and Slots system like in QT. Though I have no clue how to do such a thing myself.
Thank you for reading; I hope you have some suggestions.
Well, if you recognize which feature of JavaScript functions makes this possible, it's not too hard to do the same in C++. In JavaScript functions also have closures, which regular function in C++ don't have. But C++ lambdas are of a closure type. And if one defines bunny to be something which can both hold an object of a closure type, and be reassigned, you're all set.
The C++ standard library offers a nice default choice for this, in the form of std::function. We can just re-write your original JavaScript as follows:
std::function<void()> bunny = [] {
std::cout << "The bunny jumped.\n";
};
auto oldBunny = std::move(bunny);
bunny = [oldBunny] {
oldBunny();
std::cout << "The bunny also ran.\n";
};
bunny();
You can use functors.
#include <iostream>
#include <string>
class Base
{
public:
virtual std::string operator ()()
{
return "Base call";
}
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual std::string operator()()
{
return "Wrapper: " + Base::operator()();
}
};
int main()
{
Base* pFun = new Base;
std::cout << "Now check Base: " << (*pFun)() << std::endl;
delete pFun;
pFun = new Derived;
std::cout << "Now check Derived: " << (*pFun)() << std::endl;
return 0;
}
Assuming the goal is to allow the calling code to extend the program's functionality beyond what the initial code provided, I might use a user-updatable array of functor-objects, something like this:
#include <iostream>
#include <memory>
class Function
{
public:
virtual void Call() = 0;
};
typedef std::shared_ptr<Function> FunctionSharedPointer;
class OldBunny : public Function
{
public:
virtual void Call()
{
std::cout << "The bunny jumped." << std::endl;
}
};
class NewBunny : public Function
{
public:
NewBunny(FunctionSharedPointer oldFunction) : _oldFunction(oldFunction) {/* empty */}
virtual void Call()
{
_oldFunction->Call();
std::cout << "The bunny also ran." << std::endl;
}
private:
FunctionSharedPointer _oldFunction;
};
enum {
FUNCTION_BUNNY,
// other functions could be declared here later...
NUM_FUNCTIONS
};
// Our table of functions that the user can Call() if he wants to
static FunctionSharedPointer _functionTable[NUM_FUNCTIONS];
// Wrapper function, just to keep users from accessing our table directly,
// in case we ever want to change it to something else
void CallFunction(int whichFunction)
{
_functionTable[whichFunction]->Call();
}
// Another wrapper function
void SetFunction(int whichFunction, FunctionSharedPointer newFunctionDefinition)
{
_functionTable[whichFunction] = newFunctionDefinition;
}
// And another
FunctionSharedPointer GetFunction(int whichFunction)
{
return _functionTable[whichFunction];
}
int main(int argc, char ** argv)
{
// Our default function values get set here
SetFunction(FUNCTION_BUNNY, std::make_shared<OldBunny>());
std::cout << "before:" << std::endl;
CallFunction(FUNCTION_BUNNY);
// Now let's update an entry in our function table to do something different!
FunctionSharedPointer op = GetFunction(FUNCTION_BUNNY);
FunctionSharedPointer np = std::make_shared<NewBunny>(op);
SetFunction(FUNCTION_BUNNY, np);
std::cout << "after:" << std::endl;
CallFunction(FUNCTION_BUNNY);
return 0;
}
void bunny()
{
cout << "The bunny jumped." << endl;
}
void oldBunny()
{
bunny();
}
void newBunny()
{
bunny();
cout << "The bunny also ran." << endl;
}
#define bunny newBunny
int main()
{
bunny();
return 0;
}
If you don't need oldBunny(), just remove it.

C++: How to store various member functions of different classes for later use

thanks in advance for your support.
I'm using C++11 and I want to store public member functions of some classes for later use as callback functions; e.g. I want to store some functions that matches this template: void(classname::*)(void). As far as I know, I have to store their objects too, It's fine. For example:
// PSEUDO CODE
class A {
public:
void myfunc() {}
}myobj;
class B {
public:
void myfunc2() {}
}myobj2;
/* storing */
mystorageclass storage;
storage.push(&myobj, &A::myfunc);
storage.push(&myobj2, &B::myfunc2);
/* call them back */
(storage[0].object->*(storage[0].callback))();
(storage[1].object->*(storage[1].callback))();
Is there any safe and generic way to do that? Actually I've found a way, but I'm not sure how much it's portable across processors or compilers.
//test.cpp - compiled with: g++ test.cpp -o test -std=c++11
#include <iostream>
#include <vector>
class A {
public:
void myfunc() { std::cout << "Test A::myfunc()" << std::endl; }
}myobj;
class B {
public:
void myfunc2() { std::cout << "Test B::myfunc2()" << std::endl; }
}myobj2;
struct Callback {
void* object;
void(* method)(void*);
};
std::vector<Callback> callbackList;
template<typename FunctionPtr>
void add(void* object, FunctionPtr fptr) {
Callback cb;
cb.object = object;
cb.method = (void(*)(void*))(*(void**)(&fptr));
callbackList.push_back(cb);
}
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
//call them back
callbackList[0].method(callbackList[0].object);
callbackList[1].method(callbackList[1].object);
}
And another way to do; I feel this is much more safe:
//test2.cpp - compiled with: g++ test2.cpp -o test2 -std=c++11
#include <iostream>
#include <vector>
class A {
public:
void myfunc() { std::cout << "Test A::myfunc()" << std::endl; }
}myobj;
class B {
public:
void myfunc2() { std::cout << "Test B::myfunc2()" << std::endl; }
}myobj2;
struct Callback {
struct A;
A* object;
void(A::* method)();
void call() {
(object->*method)();
}
};
std::vector<Callback> callbackList;
template<typename FunctionPtr>
void add(void* object, FunctionPtr fptr) {
Callback cb;
cb.object = (Callback::A*)object;
cb.method = (void(Callback::A::*)())(fptr);
callbackList.push_back(cb);
}
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
//call them back
callbackList[0].call();
callbackList[1].call();
}
Does these usages are safe? Or what do you suggest instead of these.
Thanks.
Replace Callback with std::function<void()>.
Replace add with
template<class T, class R, class U>
void add(T* object, R(U::*ptr)()) {
Callback cb = [object, ptr]{ object->ptr(); };
callbackList.push_back(cb);
// or just
// callbackList.push_back([object, ptr]{ object->ptr(); });
}
note that this supports passing in pointers-to-parent member functions, and callbacks that do not return void and discarding the result.
std::function stores a generic "call this later". You pass a type compatible with the return value, and args compatible with what you want to call later, in the template signature argument of std::function<signature>. In this case, <void()>.
Problem with the second version
In the line
cb.method = (void(*)(void*))(*(void**)(&fptr));
you are casting a function pointer to void**. I am not sure that is supported by the standard. My guess is it is not. I know casting a function pointer to void* is not supported by the standard. See Print an address of function in C++, g++/clang++ vs vc++ , who is rght? for details.
And then, you proceed to use:
callbackList[1].method(callbackList[1].object);
This relies on conventions used by a compiler to pass this as the first hidden argument when calling a member function of a class. There is no guarantee that the method is used by all compilers. The standard does not explicitly state that.
Problem with the third/last version
You are using:
cb.object = (Callback::A*)object;
cb.method = (void(Callback::A::*)())(fptr);
regardless of whether the object type is A or B. This is cause for undefined behavior. The standard does not support casting of an object pointer to any old pointer type.
A Cleaner Version
Use a base class for Callback.
struct Callback {
virtual ~Callback() = 0;
virtual void call() = 0;
};
Then, use a class template for the real Callbacks.
template <typename T>
struct RealCallback : public Callback
{
RealCallback(T* obj, void (T::*m)(void)) : object(obj), method(m) {}
virtual void call()
{
(object->*method)();
}
T* object;
void (T::*method)();
};
With this, you won't be able to store a list of Callback objects but you can store a list of shared_ptr<Callback>s.
std::vector<std::shared_ptr<Callback>> callbackList;
Here's a complete program that does not rely on any ugly casts and works perfectly.
//test.cpp - compiled with: g++ test.cpp -o test -std=c++11
#include <iostream>
#include <vector>
#include <memory>
class A {
public:
void myfunc() { std::cout << "Test A::myfunc() on " << this << std::endl; }
}myobj;
class B {
public:
void myfunc2() { std::cout << "Test B::myfunc2() on " << this << std::endl; }
}myobj2;
struct Callback {
virtual void call() = 0;
};
template <typename T>
struct RealCallback : public Callback
{
RealCallback(T* obj, void (T::*m)(void)) : object(obj), method(m) {}
virtual void call()
{
(object->*method)();
}
T* object;
void (T::*method)();
};
std::vector<std::shared_ptr<Callback>> callbackList;
template<typename T>
void add(T* object, void (T::*fptr)()) {
RealCallback<T>* cb = new RealCallback<T>(object, fptr);
callbackList.push_back(std::shared_ptr<Callback>(cb));
}
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
std::cout << "myobj: " << &myobj << std::endl;
std::cout << "myobj2: " << &myobj2 << std::endl;
//call them back
callbackList[0]->call();
callbackList[1]->call();
}
Update, in response to comment by Yakk
I think Yakk's suggestion makes sense. You can remove the classes Callback and RealCallback with
using Callback = std::function<void()>;
std::vector<Callback> callbackList;
Then, add can be simplified to:
template<class T>
void add(T* object, void(T::*ptr)()) {
callbackList.push_back([object, ptr]{ (object->*ptr)();});
}
With those changes, main needs to be slightly updated to:
int main() {
//add to list for later use
add(&myobj, &A::myfunc);
add(&myobj2, &B::myfunc2);
std::cout << "myobj: " << &myobj << std::endl;
std::cout << "myobj2: " << &myobj2 << std::endl;
// Updated. Can't use callbackList[0]->call();
//call them back
callbackList[0]();
callbackList[1]();
}
Try with std::function or std::bindboth of them need to keep the reference to the instance:
#include <string>
#include <iostream>
#include <functional>
using namespace std;
class MyClass
{
int _value;
public:
MyClass(int value)
{
_value = value;
}
void food()
{
cout << "Foo is doing something whit value: " << _value << endl;
}
void bar()
{
cout << "Bar is doing something whit value: " << _value << endl;
}
};
int main()
{
MyClass* c1 = new MyClass(1);
MyClass* c2 = new MyClass(2);
cout << "Using 'std::function':" << endl;
std::function<void(MyClass&)> food = &MyClass::food;
std::function<void(MyClass&)> bar = &MyClass::bar;
food(*c1);
bar(*c1);
food(*c2);
bar(*c2);
cout << "Using 'std::bind':" << endl;
auto foodBind = std::bind(&MyClass::food, std::placeholders::_1);
auto barBind = std::bind(&MyClass::bar, std::placeholders::_1);
foodBind(*c1);
barBind(*c1);
foodBind(*c2);
barBind(*c2);
system("PAUSE");
};
the Output is:

c++ decorator pattern, static polymorphism with templates and registering callback methods

I am attempting to use static polymorphism to create a decorator pattern.
As to why I do not use dynamic polymorphism, please see this QA. Basically, I could not dynamic_cast to each decorator so as to access some specific functionality present only in the decorators (and not in the base class A).
With static polymorphism this problem has been overcome, but now I cannot register all the et() methods from the decorators back to the base class A (as callbacks or otherwise), thus when A::et() gets called, only A::et() and Z::et() get executed. I want all of A,X,Y,Z ::et() to be executed (the order for X,Y,Z does not matter).
How can I do that using the following structure?
I can see in wikipedia that CRTP should allow you to access member of a derived class using static_cast, but how do you approach the problem when there are multiple derived template classes?
If this is not possible with static polymorphism but it is possible with dynamic polymorphism could you reply to the other question?
struct I {
virtual void et() = 0;
};
class A : public I {
public:
A() {
cout << "A::ctor " ;
decList.clear();
}
void regDecorator(I * decorator)
{
if (decorator) {
cout << "reg= " << decorator << " ";
decList.push_back(decorator);
}
else
cout << "dec is null!" <<endl;
}
virtual void et()
{
cout << "A::et ";
cout << "declist size= " << decList.size() << endl;
list<I*>::iterator it;
for( it=decList.begin(); it != decList.end(); it++ )
static_cast<I *>(*it)->et();
}
std::list<I*> decList; //FIXME
};
template<typename Base>
class X: public Base {
public:
X(){
cout << "X::ctor ";
Base::regDecorator(this);
}
virtual void et(){
cout << "X::et" <<endl;
}
};
template<typename Base>
class Y: public Base {//public D {
public:
Y(){
cout << "Y::ctor ";
Base::regDecorator(this);
}
void et(){
cout << "Y::et" <<endl;
}
};
template<typename Base>
class Z: public Base {//public D {
public:
Z() {
cout << "Z::ctor ";
Base::regDecorator(this);
}
void et(){
cout << "Z::et" <<endl;
}
};
int main(void) {
Z<Y<X<A> > > mlka;
cout << endl;
mlka.et();
return 0;
}
This structure is to be used as a reference for data acquisition from a set of sensors. class A is the base class and contains common functionality of all the sensors. This includes:
- data container (f.e. `boost::circular_buffer`) to hold an amount of timestamped sample data acquired from the sensor.
- a Timer used to measure some timed quantities related to the sensors.
- other common data and calculation methods (fe. `calculateMean()`, `calculateStdDeviation()`)
In fact the A::timer will call A::et() on completion in order to perform some statistical calculations on the sampled data.
Similarly, X,Y,Z are types of sensor objects each with responsibility to extract different type of information from the sampled data. and X,Y,Z::et() perform a different type of statistical calculation on the data. The aim is perform this calculation as soon as the A::Timer waiting time elapses. This is why I want to have access to all of X,Y,Z::et() from A::et(). Is it possible without affecting the static polymorphism shown in the example?
Thank you
You started using mixins, so use them to the end.
It follows a minimal, working example:
#include<iostream>
struct I {
virtual void et() = 0;
};
template<typename... T>
struct S: I, private T... {
S(): T{}... {}
void et() override {
int arr[] = { (T::et(), 0)..., 0 };
(void)arr;
std::cout << "S" << std::endl;
}
};
struct A {
void et() {
std::cout << "A" << std::endl;
}
};
struct B {
void et() {
std::cout << "B" << std::endl;
}
};
int main() {
I *ptr = new S<A,B>{};
ptr->et();
delete ptr;
}
As in the original code, there is an interface I that offers the virtual methods to be called.
S implements that interface and erases a bunch of types passed as a parameter pack.
Whenever you invoke et on a specialization of S, it invokes the same method on each type used to specialize it.
I guess the example is quite clear and can serve as a good base for the final code.
If I've understood correctly the real problem, this could be a suitable design for your classes.
EDIT
I'm trying to reply to some comments to this answer that ask for more details.
A specialization of S is all the (sub)objects with which it is built.
In the example above, S<A, B> is both an A and a B.
This means that S can extend one or more classes to provide common data and can be used as in the following example to push around those data and the other subobjects:
#include<iostream>
struct I {
virtual void et() = 0;
};
struct Data {
int foo;
double bar;
};
template<typename... T>
struct S: I, Data, private T... {
S(): Data{}, T{}... {}
void et() override {
int arr[] = { (T::et(*this), 0)..., 0 };
(void)arr;
std::cout << "S" << std::endl;
}
};
struct A {
void et(Data &) {
std::cout << "A" << std::endl;
}
};
struct B {
void et(A &) {
std::cout << "B" << std::endl;
}
};
int main() {
I *ptr = new S<A,B>{};
ptr->et();
delete ptr;
}

Making all class methods call the same function

So, I've got this situation:
#include "ActionLog.h"
class Library{
ActionLog aLog;
// ... the rest of it is private, mind you :D
public:
Library(...);
void addBook(...);
void removeBook(...);
// ... aaand there's a whole bunch of these :)
};
Now, class ActionLog has a public method void log(...);. It should, once implemented, record the beginning of any activity listed as a method of class Library (and eventually it's success/failure, which is optional).
I'm wondering this: Is there some more elegant way of making every class Library's method call the aLog.log(...); method when/before it starts executing? By "elegant" I mean other than just calling it explicitly in every single method...
I am aware of the Python version of the solution for the similar problem, but I'm not familiar with Python, so I'm not even sure that the same class-related principles apply.
C++ doesn't have any means of reflection built-in. There's no way to list methods neither in runtime, nor in compile-time. The best you can do is to hide logging into some #define that you will use to define every method, but preprocessor usage is an antipattern in modern C++.
Stick to the current approach.
As polkovnikov.ph said, without reflection you wouldn't be able to use the python's approach to this.
Just for fun I am going to leave this here but I wouldn't recommend its use:
#include <iostream>
class Logger
{
public:
void log(std::string entry)
{
std::cout << entry << std::endl;
}
};
class A
{
Logger mylog;
public:
void foo()
{
std::cout << "Doing foo" << std::endl;
}
Logger& getLogger()
{
return mylog;
}
};
#define CALL_FUNC_AND_LOG(obj,func) \
{ obj.getLogger().log("Logging "#func); obj.func(); }
int main()
{
A a;
CALL_FUNC_AND_LOG(a,foo);
return 0;
}
http://ideone.com/q0VHj6
Or another version that automatically logs the end of scope of the method.
#include <iostream>
class Logger
{
std::string _entry;
public:
Logger(std::string entry)
{
_entry = entry;
std::cout << "Starting execution of " << entry << std::endl;
}
~Logger()
{
std::cout << "Ending execution of " << _entry << std::endl;
}
};
class A
{
public:
void foo()
{
std::cout << "Doing foo" << std::endl;
}
};
#define CALL_FUNC_AND_LOG(obj,func) \
{ \
Logger _mylogger(""#func); \
obj.func(); \
\
}
int main()
{
A a;
CALL_FUNC_AND_LOG(a,foo);
return 0;
}
http://ideone.com/DHf3xu

Mixin layers & static binding

I'm currently playing with mixin layers designs, and I'm stuck with an
annoying problem.
Let's consider the following basic mixin layer:
template <typename Next>
struct Layer1 : public Next
{
struct A : public Next::A
{
void f() { g(); }
void g() {}
};
};
Nothing fancy here, just a simple mixin with 2 methods f() and g().
Notice that the g() call from f() is is statically binded to this
specific Layer1::A::g().
Now, what I want is to be able to completely hook the methods of this
mixin to implement, say, a logging layer:
template <typename Next>
struct Layer2 : public Next
{
struct A : public Next::A
{
void f()
{
std::cout << "Layer2::A::f() [enter]" << std::endl;
Next::A::f();
std::cout << "Layer2::A::f() [leave]" << std::endl;
}
void g()
{
std::cout << "Layer2::A::g() [enter]" << std::endl;
Next::A::g();
std::cout << "Layer2::A::g() [leave]" << std::endl;
}
};
};
Considering Layer2<Layer1<...>>, the problem here is that any call of
f() and g() from a layer above Layer2 will properly cascade down to
the Layer2::A::g(), and thus display the proper logging messages. But
any call of f() and g() from below Layer2 will not log anything since
the call would have been statically binded to the g() available at the
time the call was made.
This means that calling f() from any layer above Layer2 will obviously
still always call Layer1::A::g() from Layer1::A::f() and not display
the logging messages.
I came up with 2 solutions to this problem:
Virtuality: clearly not acceptable. The whole point of mixin layers
is to avoid virtuality when not necessary.
Adding a template parameter to the layers to provide the previous
layer, something of the kind.
.
template <typename Next, template <typename> class Prev>
struct Layer2 : public Next
{
typedef Next next_t;
struct A : public Next::A
{
void f()
{
std::cout << "Layer2::A::f() [enter]" << std::endl;
Next::A::f();
std::cout << "Layer2::A::f() [leave]" << std::endl;
}
void g()
{
std::cout << "Layer2::A::g() [enter]" << std::endl;
Next::A::g();
std::cout << "Layer2::A::g() [leave]" << std::endl;
}
};
};
template <typename Next, template <typename> class Prev>
struct Layer1 : public Next
{
typedef Next next_t;
struct A : public Next::A
{
void f()
{
std::cout << "Layer1::A::f() [enter]" << std::endl;
((typename Prev<Layer1<Next,Prev> >::A*)this)->g();
std::cout << "Layer1::A::f() [leave]" << std::endl;
}
void g()
{
std::cout << "Layer1::A::g() [enter]" << std::endl;
std::cout << "Layer1::A::g() [leave]" << std::endl;
}
};
};
typedef Layer2<Layer1<Layer0,Layer2>,NullType> Application;
Well, it works, but I would like to hide this second template
parameter since it is redundant.
I wondered if any of you ever encountered such problem, and what
solutions did you developped to solve it, since there is a clear lack
of articles on mixin layers.