Callback function in two classes - c++

Hello I have a problem with a callback function. I'm relative new to c++.
I have two classes helper and exporter:
Helper:
class Helper {
typedef Bool (*IterationCallback)(BaseObject *op);
public: Int32 RecurseHierarchy (BaseObject* op, IterationCallback callback) {
Int32 count = 0;
while (op) {
if (callback(op)) {
count++;
count += RecurseHierarchy(op->GetDown(), callback);
op = op->GetNext();
}
}
return count;
}
};
Exporter:
class Exporter {
private: Helper helper;
private: Bool writeT3D (Filename exportT3D) {
string filepath = C4DStringToStdString(exportT3D.GetString());
t3DFile.open(filepath.c_str());
writeBegin();
// Iterate all objects in the document and writes an actor
BaseDocument *doc = GetActiveDocument();
Int32 count = helper.RecurseHierarchy(doc->GetFirstObject(), this->WriteActor);
writeEnd();
t3DFile.close();
return true;
}
};
And I'm getting the errorC3867 function call missing argument list and I should use &Exporter::WriteActor. But I can't solve the problem. Can someone help me?

The problem
Assuming WriteActor to be a member function of Exporter, then its type is probably:
Bool (Exporter::*)(BaseObject*)
which is not compatible with:
Bool (*)(BaseObject*)
The reason is that in the former an implicit parameter is passed of type Exporter* (normally accessible inside the member function as this), while in the latter this does not happen.
One solution
For the above reason, you need to explicitly pass this implicit argument of type Exporter*, before passing the resulting function to RecurseHierarchy.
In your case you can use std::bind as follows:
using namespace std::placeholders;
auto fn = std::bind(&Exporter::WriterActor, this, _1);
Int32 count = helper.RecurseHierarchy(doc->GetFirstObject(), fn);
and then modify Helper to take any callable object:
struct Helper {
template<typename Fn>
Int32 RecurseHierarchy(BaseObject* op, Fn callback) {
Int32 count = 0;
while (op) {
if (callback(op)) {
count++;
count += RecurseHierarchy(op->GetDown(), callback);
op = op->GetNext();
}
}
return count;
}
};
Live demo
The above change is especially important if you also want to allow std::function objects and lambdas to be passed.

Related

How to get function pointer arguments names using clang LibTooling?

Say I analyze a code like this:
struct Foo
{
void(*setParam)(const char* name, int value);
};
I use clang LibTooling and get FieldDecl on a setParam.
I figured I can get argument types like so:
auto ft = fieldDecl->getFunctionType()->getAs<FunctionProtoType>();
for (size_t i = 0; i < fpt->getNumParams(); i++)
{
QualType paramType = fpt->getParamType(i);
....
}
But how do I get argument names? ("name" and "value" in that case) Is that even possible or I need to manually look into source (with SourceManager)?
I don't think it's possible to get the parameter names directly from the type, since they're not part of the type information.
But your task can be accomplished by one more visiting to the function pointer declaration:
class ParmVisitor
: public RecursiveASTVisitor<ParmVisitor>
{
public:
bool VisitParmVarDecl(ParmVarDecl *d) {
if (d->getFunctionScopeDepth() != 0) return true;
names.push_back(d->getName().str());
return true;
}
std::vector<std::string> names;
};
Then the calling site is:
bool VisitFieldDecl(Decl *d) {
if (!d->getFunctionType()) {
// not a function pointer
return true;
}
ParmVisitor pv;
pv.TraverseDecl(d);
auto names = std::move(pv.names);
// now you get the parameter names...
return true;
}
Pay attention to the getFunctionScopeDepth() part, it's necessary because a function parameter might be a function pointer itself, something like:
void(*setParam)(const char* name, int value, void(*evil)(int evil_name, int evil_value));
getFunctionScopeDepth() being 0 ensures that this parameter is not in a nested context.

C++ How to create a function pointer to an overloaded templated function

So I have an overloaded templated function that needs to be passed down to a thread. I don't know how to distinguish overloaded functions to a function pointer.
template<typename T>
void DetectChange(T& variable, T& notify) { // must be a thread, else it's useless
T original = variable;
while (true) {
if (variable != original) { // change detected
notify = variable; // send notification
variable = original; // reset to original
}
}
}
template<typename T>
void DetectChange(T& variable, void (* notify)()) { // must be a thread, else it's useless (template, function pointer)
T original = variable;
while (true) {
if (variable != original) { // change detected
notify(); // do notification function
variable = original; // reset to original
}
}
}
int main() {
int x = 3;
void(*function)();
function = &DetectChange; // how to distinguish which overloaded templated function
std::thread detect = std::thread(&function, x, doSomething);
x++; // change variable
return 0;
}
Your problem is that function doesn't match either overload. function is declared taking no arguments but both available overloads take at least two. And the function-pointer type has to match down to references etc.
void (*ptr)(int &, int&) = &DetectChange;
Of course that would fail to compile because int isn't a valid T but it should give you the idea.

Is there a possibility to make a function wrapper that runs the injected code and returns the same data as the injected function?

I am toying with this idea for a while but cant seem to wrap my head around it.
Basically what I want to do is create a general Timer class that times all the functions that are passed to it. Averaging it when the same function is called multiple times so it has to store it somehow. It should therefore use the function name to store the task and average it when it occurs more than once.
Pseudoish code of what it should look like.
Class FunctionTaks
{
std::string d_name;
double d_execution_time;
}
Class Timer
{
private:
std::vector<FunctionTask> d_tasks;
public:
template <typename Function, typename ReturnType>
ReturnType time(Function f)
{
// check if function f is timed for first time
// start timer
// run function f
auto r = f.invoke();
// stop timer
// store function name and time, average if more than once
// return whatever f should return
return r;
}
void report() const;
}
I dont really know how to do this, especially when Function f has a different amount of arguments.
Timer t;
t.time(foo());
t.time(bar());
t.time(foo());
t.report();
I basically have a few core issues.
How to let a function wrapper return the same type that the injected code is suppose to return.
How to obtain the function name that is being injected.
The wrapper should not be limited by arguments passed on to the injected function. How to give the injected function the freedom of arguments.
On the other hand I dont really care about the arguments and return type, the wrapper should simply run the injected function as is and perform some timings and then return whatever the injected function is suppose to return.
C++11 but why templates? You need lambda expressions:
typedef void(*TimerFunction)();
void time(TimerFunction fun) {
// start timer
fun();
// stop timer
}
int fun1() { return 1; }
int fun2() { return 2; }
string fun3() { return string("Test"); }
main() {
int ret1, ret2;
string ret3;
t.time([&ret1]() { ret1 = fun1(); });
t.time([&ret2]() { ret2 = fun2(); });
t.time([&ret3]() { ret3 = fun3(); });
}
That's the concept. For details: C++ lambda with captures as a function pointer
With C++11 you can use variable template parameters:
class TimerFoo {
public:
template <class Foo, class... Args> TimerFoo(Foo foo, Args... args) {
// ... start timer
foo(args...);
// ... stop timer
}
};
And use e.g.:
TimerFoo tf = TimerFoo(foo, 1, 2, 3);
Ofcourse you need some field in TimerFoo that will store the measured time...
Edit:
To be able to return a value of your function using this approach you could change the above code to:
#include <iostream>
using namespace std;
class TimerFoo {
public:
template <class Foo, class... Args> auto run(Foo foo, Args... args) -> decltype(foo(args...)) {
// ... start timer
auto result = foo(args...);
// ... stop timer
return result;
}
};
int foo(int a, int b) {
return 2;
}
int main() {
TimerFoo tf;
cout << tf.run(foo, 1, 2) << endl; // output: 2
}

pointer on method as an argument

To avoid code duplication, I'm tring to pass pointers to functions as arguments of a static method.
I have a class (Geo) with only static methods. One of this methods (+++Geo::traceRay(+++)) should just display(Geo::display(+++)) few things, then return an int.
Another class (Las) needs to use the Geo::traceRay(+++) method, but should display(Las::display(+++)) someting else.
So I try to pass a pointer to function argument to the Geo::traceRay(+++, pointer to function) method. the pointed functon will the right "display()" method.
Up to now, passing the first pointer to display() is not an issue, but I can't find how to do it with the second one.
class Geo
{
public:
static bool display(int pix);
static int traceRay(int start, int end, bool (*func)(int) = &Geo::display); // no issue with this default parameter
};
class Las
{
public:
bool display(int pix);
void run();
};
int Geo::traceRay(int start, int end, bool (*func)(int))
{
for (int i = start; i < end ; ++i )
{
if((*func)(i)) return i;
}
return end;
}
bool Geo::display(int pix)
{
cout << pix*100 << endl;
return false;
}
bool Las::display(int pix)
{
cout << pix << endl;
if (pix == 6) return true;
return false;
}
void Las::run()
{
bool (Las::*myPointerToFunc)(int) = &display; // I can just use display as a non member class, but it should stay a member
Geo::traceRay(0,10, myPointerToFunc); // issue here!
}
int main()
{
Geo::traceRay(0,10); // use the "normal display" = the default one// OK
Las myLas;
myLas.run();
return 0;
}
You can't pass a member function pointer as a function pointer. I presume making Las::display static is not an option. In that case, I would suggest taking a std::function and using std::bind to bind the current instance:
static int traceRay(int start, int end, std::function<bool(int)> func = &Geo::display);
...
Geo::traceRay(0,10, std::bind(&Las::display, this, std::placeholders::_1));
Also, in both cases, you can call func by:
func(i);
No need to dereference it first.
What Chris suggests is great if that's as far as it goes.
Another approach to this, which would be beneficial if you have several shared functions like that, would be to use an interface (with a virtual method Display(+++)) with two implementations, put an instance of the implementation in question in each of Geo and Las (or Las could directly implement the interface). Then traceRay takes a reference to the interface base class and calls the display method on it.

User defined attributes and compile time evaluation for setting class member variables

I'm trying to learn a little more about D's compile time evaluation and understand how its templates, mixins, attributes, etc all work. One thing I'd like to try and do is figure out an elegant way to mark a class's members as being serializable or loadable from a database. In the example below, I've created a tuple that lists which members to use when reading or (later on) serializing the instance.
My first question is, is this a proper usage of tuples as it stands below? And secondly, if so, is there a way to generate this tuple automatically at compile time using the user defined attributes I've assigned to the relevant member variables? I've dug through the various documentation pages like http://dlang.org/attribute.html and http://dlang.org/phobos/std_traits.html but I can't seem to figure out how to use them properly for this purpose (i.e. looping through a class's members and determining which variables have the desired attribute). I'm also not quite certain if I have completely the wrong idea about how attributes are supposed to be used. Any suggestions on the best way to go about this would be appreciated.
enum ENCODABLE = 1;
alias string[string] Row;
template Tuple (T...) { alias T Tuple; }
class A {
#(ENCODABLE) string name;
#(ENCODABLE) int x;
int* p;
alias Tuple!("name","x") encodables;
this(Row row) {
foreach (var; encodables) {
__traits(getMember, this, var) = to!(typeof(__traits(getMember, this, var)))(row[var]);
}
}
}
void main() {
Row row = ["name":"Asdf", "x":"120"]; // Simulated database row
auto a = new A(row);
writefln("%s,%d,%d", a.name, a.x, a.p); // Asdf,120,null
}
This isn't much of an answer, but I used them by defining my own helper templates, and using structs as UDAs (with their values indicating parameters). The helper templates are here:
https://github.com/CyberShadow/ae/blob/master/utils/meta.d#L133
They're used here, to allow overriding the JSON field for a JSON serializer/unserializer:
https://github.com/CyberShadow/ae/blob/master/utils/json.d#L505
I've managed to get it working with the following code, and a little help from the isValueInTuple template based on code provided in CyberShadow's answer. It still feels a bit clunky, but seems to get the job done. Comments/criticism welcome if I'm doing something horrible against the nature of templates!
enum {
ENCODABLE = "ENCODABLE",
};
alias string[string] Row;
template Tuple(T...) { alias T Tuple; }
template isValueInTuple(string s, T...) {
static if (T.length == 0) {
enum bool isValueInTuple = false;
} else static if (T.length == 1) {
static if (is(typeof(T[0]) == typeof(s))) {
enum bool isValueInTuple = T[0] == s;
} else {
enum bool isValueInTuple = false;
}
} else {
enum bool isValueInTuple = isValueInTuple!(s, T[0]) || isValueInTuple!(s, T[1..$]);
}
}
template GenEncodables(U) {
string GenEncodables() {
string ret = "alias Tuple!(";
int fn = 0;
foreach (index, field; __traits(allMembers, U)) {
static if (field != "Monitor") { // better way to avoid compilation errors here?
static if (isAssignable!(typeof(mixin(U.stringof~"."~field)))) {
static if (isValueInTuple!(ENCODABLE, __traits(getAttributes, mixin(U.stringof~"."~field)))) {
if (fn++)
ret ~= ",";
ret ~= `"`~field~`"`;
}
}
}
}
ret ~= ") encodables;";
return ret;
}
}
mixin template Encodables() {
mixin(GenEncodables!(typeof(this)));
}
class A {
#ENCODABLE string name;
#ENCODABLE int x;
int *p;
this() {}
mixin Encodables; // must come after this() definition, apparently!
this(Row row) {
foreach (var; encodables) {
pragma(msg, "Reading parameter "~var~" from row");
__traits(getMember, this, var) = to!(typeof(__traits(getMember, this, var)))(row[var]);
}
}
}