I have this minimal sample code:
#include <functional>
#include <iostream>
#include <vector>
template<class ReadFileCallback>
void fileMgr_ReadWithCallback(std::string filename, ReadFileCallback callback) {
callback("OK");
}
void globalReadResult(std::string result) {
std::cout << "ReadResult in global function: result=" << result << std::endl;
}
class MyClass {
public:
MyClass() {};
~MyClass() {};
void Read() {
fileMgr_ReadWithCallback("file", globalReadResult);
//fileMgr_ReadWithCallback("file", this->ReadResult);
}
void ReadResult(std::string result) {
std::cout << "ReadResult in member function: result=" << result << std::endl;
}
};
int main()
{
MyClass c;
c.Read();
return 0;
}
For callback function I'd like to use a non-static class member MyClass::ReadResult. It would also be good to know before calling the callback if the object is still valid (non-destructed), because otherwise the program will fail I guess.
How shall I change this code to be able to use the MyClass object's ReadResult as callback?
You can just wrap it into a lambda:
class MyClass {
public:
MyClass() {};
~MyClass() {};
void Read() {
fileMgr_ReadWithCallback("file", [this](const std::string& result){ this->ReadResult(result); });
}
void ReadResult(std::string result) {
std::cout << "ReadResult in member function: result=" << result << std::endl;
}
};
You may use std::bind.
#include <functional>
#include <iostream>
#include <vector>
#include <functional>
template<class ReadFileCallback>
void fileMgr_ReadWithCallback(std::string filename, ReadFileCallback callback) {
callback("OK");
}
void globalReadResult(std::string result) {
std::cout << "ReadResult in global function: result=" << result << std::endl;
}
class MyClass {
public:
MyClass() {};
~MyClass() {};
void Read() {
using std::placeholders::_1;
//std::function<void(std::string)> func = std::bind( &MyClass::ReadResult, this, _1);
auto func = std::bind( &MyClass::ReadResult, this, _1);
fileMgr_ReadWithCallback("file", func);
//
// or
// fileMgr_ReadWithCallback("file", std::bind( &MyClass::ReadResult, this, _1));
}
void ReadResult(std::string result) {
std::cout << "ReadResult in member function: result=" << result << std::endl;
}
};
int main()
{
MyClass c;
c.Read();
return 0;
}
Related
I have a class, classB which has several functions which I would like to specialize based on an enumerator template S.
I have the following example:
#include <iostream>
#include <string>
#include <array>
typedef std::array<double, 3> vec;
enum Op {Op1, Op2, Op3};
template<class T, enum Op S=Op1>
class classA
{
public:
class innerClassA
{
public:
void foo() const
{
std::cout <<"Operation 1" << std::endl;
}
};
};
template<class T>
class classB
{
public:
template <Op S = Op1>
void myFunc()
{
typename classA<T, S>::template innerClassA myInnerClassObj;
for (int i = 0; i < 10; i++)
myInnerClassObj.foo();
}
// Other functions the I would like to able to speciallize afterwards based on template S
void myFunc2() { std::cout << "Func 2" << std::endl; }
void myFunc3() { std::cout << "Func 3" << std::endl; }
};
template<>
void classA<vec, Op2>::innerClassA::foo() const
{
std::cout << "Operation 2" << std::endl;
}
template<>
void classA<vec, Op3>::innerClassA::foo() const
{
std::cout << "Operation 3" << std::endl;
}
int main(int argc, char** argv)
{
classB<vec> obj;
obj.myFunc();
obj.myFunc2();
obj.myFunc<Op2>();
obj.myFunc<Op3>();
return 0;
}
In the above example. The function myFunc has a template parameter based on the enumerator. In the main function, I can call the specialized version based on the value of the enumerator. I would also like to do the same for the other functions,myFunc2 however, always having to put:
template <Op S = Op1>
someFunction()
is quite bothersome. Is there any other way to specify that all functions in a class have a default template based on the enumerator?
Kind regards
No, there is not, apart from macros.
#define OPFUNC template<Op S = Op1> void
OPFUNC myFunc() {}
OPFUNC myFunc2() {}
...
#undef OPFUNC
I've been having some trouble recently with an invoker class I've created. Reason is so I can parse an address through the class constructor and have it handle calling methods that are in memory. Problem is, when I go to return a class object type, it throws an error "Cannot convert from std::string to InvokerType". Any help is appreciated.
template <class InvokerType>
class Invoker {
public:
Invoker(std::intptr_t address) :
address(address)
{ }
template<class... Arguments>
InvokerType invoke(Arguments&&... parameters) {
InvokerType func = (InvokerType)this->address;
return (InvokerType)func(std::forward<Arguments>(parameters)...);
}
private:
std::intptr_t address;
};
std::string test(const std::string& str) {
std::cout << str << std::endl;
return "I have returned";
}
int main(void) {
using test_print_type = std::string (*)(const std::string& str);
Invoker<test_print_type> get_value{ (std::intptr_t)test };
auto ret = get_value.invoke("Hello I am a testing function\n");
std::cout << ret << std::endl; // Errors here
std::system("PAUSE");
return 0;
}
If you want to return the value from the invoked function, I think you need to separate the return type into its own template parameter.
#include <cstdint>
#include <string>
#include <iostream>
#include <utility>
template <class ReturnType, class...Args>
class Invoker {
public:
Invoker(std::intptr_t address) :
address(address)
{ }
ReturnType invoke(Args&&... parameters) {
auto func = (ReturnType(*)(Args...)) address;
return func(std::forward<Args>(parameters)...);
}
private:
std::intptr_t address;
};
std::string test(const std::string& str) {
std::cout << str << std::endl;
return "I have returned";
}
int main(void) {
Invoker<std::string, const std::string&> get_value{ (std::intptr_t)test };
auto ret = get_value.invoke("Hello I am a testing function\n");
std::cout << ret << std::endl; // Errors here
return 0;
}
At runtime a single test is made to determine which of two functions to call and also to establish parameter value(s).
The function is then called every few seconds.
void Foo::func( std::string s);
void Foo::func( std::string s1 std::string s2, std::string s2);
Obviously, its inefficient to test( which function to call ) for every call, especially when the function and its parameter value(s) will not change once established.
I need something like this:
Test once which function to call and established parameter value(s).
Assign initialised function to some kind of callable variable.
funcVar = void Foo::func( "blah", "blah", "woof" );
or
funcVar = void Foo::func( "blah" );
Then call function;
for( every few seconds )
{
call FuncVar;
}
Is there some kind of callable variable I can use to do this?
You can simply use a lambda function object ( closure ) which you can call as often as you like.
Example:
struct Foo
{
void func( std::string s){ std::cout << "single" << s << std::endl; };
void func( std::string s1, std::string s2, std::string s3)
{
std::cout << "tripple " << s1 << " " << s2 << " " << s3 << std::endl;
}
// Select which function to call
std::function<void()> Select( int what )
{
if ( what == 1 )
{
// Create a callable object and put in also parameters
return [this]() { func("Hallo"); };
}
else
{
// The same for the other selection
return [this]() { func("This","is","tripple!"); };
}
}
};
int main()
{
Foo foo;
// Pick what you want to select
auto action = foo.Select( 2 );
for ( ;; )
{
// and call it as often you like
action();
}
}
You can use std::bind for creating a functor with stored arguments and common call operator for both your use cases. Check this snippet:
#include <string>
#include <functional>
struct Foo {
static void a(std::string) {}
static void b(std::string, std::string) {}
};
int main() {
std::function<void()> x;
if(true) {
x = std::bind(&Foo::b, "a", "b");
}
x();
return 0;
}
If you want to std::bind overloaded functions, you have to specify which one you want to use:
#include <string>
#include <functional>
#include <iostream>
#include <map>
struct Foo {
void b() { std::cout << name << ": function 1" << std::endl; }
void b(int i) {std::cout << name << ": function 2" << std::endl; }
std::string name;
};
void with_map() {
Foo f;
f.name = "with_map";
std::map<const int, std::function<void()>> map({
{10, std::bind<void(Foo::*)(), Foo&>(&Foo::b, f)},
{20, std::bind<void(Foo::*)(int), Foo&, int>(&Foo::b, f, 1)},
});
map[20]();
map[10]();
}
void without_map() {
Foo f;
f.name = "without_map";
std::function<void()> x = std::bind<void(Foo::*)(), Foo&>(&Foo::b, f);
x();
x = std::bind<void(Foo::*)(int), Foo&, int>(&Foo::b, f, 1);
x();
}
int main() {
without_map();
with_map();
return 0;
}
std::function should work here.
std:: function<void()> fun = [&s] () {/* do work*/};
if (some_condition)
{
fun = [&s1,&s2,&s3] () {/* do your work*/} ;
}
if(every few seconds)
{
fun();
}
I have created a class Base which has a function addSuccessor() that takes address of function as argument and stores it in successor. How do I pass a function of another object in addSuccessor().
Here is my program. I think my main() has some mistake.
#include <iostream>
#include<vector>
using namespace std;
class Base{
public:
void (*successor)()=NULL;
void addSuccessor ( void (*f)() )
{
successor=f;
}
void start()
{
cout<<"In Class"<<endl;
if(!successor==NULL)
successor();
else
cout<<"No Successor"<<endl;
}
};
class Second{
public:
void foo()
{
cout<<"Successor";
}
};
int main()
{
Base obj;
Second obj2;
obj.addSuccessor(&obj2.foo());
obj.start();
}
Function pointers are very limited. Use a std::function (defined in header <functional>) instead, which can store any invocable object in a type-erased manner, and provide a template member function to set the functor in which perfect forwarding is used to forward the provided functor to successor: (std::forward is defined in header <utility>)
class Base {
std::function<void()> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
successor();
} else {
std::cout << "No Successor\n";
}
}
};
Then, you can pass a lambda expression to add_successor:
obj.add_successor([&]{ obj2.foo(); });
(live demo)
As a complement to the discussion above (based on #L.F.'s answer):
#include <functional>
#include <iostream>
#include <utility>
class Base {
std::function<int(int)> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
auto z = std::invoke(successor, 100);
std::cout << "Output = " << z << "\n";
} else {
std::cout << "No Successor\n";
}
}
};
class Second {
public:
int foo(int x)
{
auto y = x + x;
std::cout << "Successor\n";
return y;
}
};
int main()
{
Base obj;
Second obj2;
obj.add_successor([&](int x)->int { return obj2.foo(x); });
obj.start();
}
i'd like to invoke runtime-bound functions of classes, that inherit a binding ability from a common class "Bindable". Is that actually possible?
Here's a stub which surely lacks a lot of template-arguments and namespaces:
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
void bindFunction (int x, auto newFn) {
mFns.insert(std::pair<int, auto>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, function> mFns;
};
class A : Bindable {
void funAone (void) {
cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
cout << "called funAtwo" <<std::endl;
}
};
class B : Bindable {
void funBone (void) {
cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
Option #1
Use a CRTP idiom to know what type of pointers to member functions can be stored:
template <typename T>
struct Bindable {
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x,newFn));
}
void invokeFunction (int key) {
(static_cast<T*>(this)->*mFns.at(key))();
}
protected:
std::map<int, void(T::*)()> mFns;
};
struct A : Bindable<A> {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
DEMO 1
Option #2
Use a type-erasure and make bindFunction a function template:
struct Bindable {
template <typename T, typename std::enable_if<std::is_base_of<Bindable, T>{}, int>::type = 0>
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x, std::bind(newFn, static_cast<T*>(this))));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, std::function<void()>> mFns;
};
struct A : Bindable {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
DEMO 2
In both cases you can use the code as follows:
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
Output:
called funAone
called funAtwo
called funBone
called funBtwo
Yes, it's possible, using std::bind. Note that auto can't be used as a function or template argument.
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
typedef std::function<void()> Function;
void bindFunction (int x, Function newFn) {
mFns.insert(std::pair<int, Function>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, Function > mFns;
};
class A : public Bindable {
public:
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
class B : public Bindable {
public:
void funBone (void) {
std::cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
std::cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, std::bind(&A::funAone, a)); // more than one way to bind
a.bindFunction(2, std::bind(&A::funAtwo, &a)); // the object parameter
b.bindFunction(1, std::bind(&B::funBone, b));
b.bindFunction(2, std::bind(&B::funBtwo, &b));
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}