What is the best way to pass callback function to std::map? - c++11

I was trying to work on the below code but the program crashes:
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef void (*callBackMethod)(string);
class CTest
{
private:
map<string, callBackMethod> mapMethod;
void testMethod(string msg)
{
cout << msg << endl;
}
public:
CTest()
{
addFunction("AA", (callBackMethod) &CTest::testMethod);
}
void addFunction(string funName, callBackMethod methodName)
{
mapMethod[funName] = methodName;
}
callBackMethod getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
return 0;
}
I have a requirement where I need to pass private methods to a map. The program compiles with warning:
converting from 'void (CTest::*)(std::__cxx11::string) {aka void (CTest::*)(std::__cxx11::basic_string<char>)}' to 'callBackMethod {aka void (*)(std::__cxx11::basic_string<char>)}'
and when I execute this, it crashes.
When I move the callback method outside of the class it works. My requirement is to make the program flow this was (hide the methods from external call which needs to be added to a map).
Looking forward to your comments.

If you need to point to both CTest member functions and free functions, then you can use std::function<void(std::string)>.
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
using callBackFunction = std::function<void(string)>;
void testFunction(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
class CTest
{
private:
map<string, callBackFunction> mapMethod;
void testMethod(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
public:
CTest()
{
addFreeFunction("AA", testFunction);
addMemberFunction("BB", &CTest::testMethod);
}
void addMemberFunction(string funName, void(CTest::*methodName)(string))
{
using std::placeholders::_1;
mapMethod[funName] = std::bind(methodName, this, _1);
}
void addFreeFunction(string funName, void(*methodName)(string))
{
mapMethod[funName] = methodName;
}
callBackFunction getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
test.runFunction("BB");
return 0;
}
Notice that CTest must insert elements into the map in a different way depending on what type of function you are passing, since for member functions you must provide the object for which it is to be invoked, this in this example. This is achived by using std::bind.

Since you want to use member variables you need to specify the signature differently in your typedef:
In C++ Builder the following can be done:
typedef void(__closure *callBackMethod)(string);
If you do that, I do suggest that you keep a smart pointer to the object that the member belongs to so that you can check if the object is still valid before calling the function otherwise it will crash the application.
The __closure keyword is a C++ Builder extension to work around the requirement to use fully qualified member names source
To handle both global and member functions we have the following:
typedef void(__closure *callBackMethodMember)(string);
typedef void (*callBackMethodGlobal)(string);
/* And then on 2 overloaded functions */
void addFunction(string funName, callBackMethodMember methodName) {}
void addFunction(string funName, callBackMethodGlobal methodName) {}

Related

copy constructor do not work in cpp template

I'm writing a test program about c++ type erasure, the code is put on the end.
when I run program , the test case 2 output as follow:
A default cstr...0x7ffe0fe5158f
obj_:0x7ffe0fe5158f objaaa 0x7ffe0fe5158f
Print A 0x7ffe0fe5158f
my machine: Linux x86-64, gcc 4.8
In my opinion, "Object obj2(a2);" makes a class Model by lvalue reference, so it should call A's copy constructor,
but actually it did not work, it makes me confused.
someone can give a explanation, thank you in advance.
the program is list as follow:
#include <memory>
#include <iostream>
class Object {
public:
template <typename T>
Object(T&& obj) : object_(std::make_shared<Model<T>>(std::forward<T>(obj))) {
}
void PrintName() {
object_->PrintName();
}
private:
class Concept {
public:
virtual void PrintName() = 0;
};
template <typename T>
class Model : public Concept {
public:
Model(T&& obj) : obj_(std::forward<T>(obj)) {
std::cout << "obj_:" << std::addressof(obj_) <<" objaaa " << std::addressof(obj) << std::endl;
}
void PrintName() {
obj_.PrintName();
}
private:
T obj_;
};
private:
std::shared_ptr<Concept> object_;
};
class A {
public:
A(A& a) {
std::cout<< "A copy cstr...a" << this << std::endl;
}
A(A&& a) {
std::cout << "A move cstr...." <<this<< std::endl;
}
A() {
std::cout << "A default cstr..." <<this<< std::endl;
}
void PrintName() {
std::cout << "Print A " << this << std::endl;
}
};
int main(void)
{
// test case 1
Object obj{A()};
obj.PrintName();
// test case 2
A a2;
Object obj2(a2);
obj2.PrintName();
return 0;
}
In Object obj2(a2);, no copy is made. T in the constructor of Object is deduced to be A&, so it instantiates Model<A&>, which stores a reference to the original a2 object as its obj_ member.
Observe that in your debug output, a2's constructor, Model's constructor and PrintName all print the same address. You can further confirm that this address is in fact &a2.

C++ 11 passing shared_pointer like with std::any

at the moment I'm facing following problem. I need a member function in a derived class that can handle different shared_ptr types and do custom stuff with it. The base class should make sure that such a member function is implemented but the specific shared_ptr types are only known when a other developer create a new derived class. Therefore, templates are not a solution due to the fact that c++ not support virtual template functions.
The shared_ptrs hold protobuf message specific publisher or subscriber. Here a snipped of code:
std::shared_ptr<Publisher<ProtobufMessageType1>> type1 = std::make_shared<ProtobufMessageType1>();
std::shared_ptr<Publisher<ProtobufMessageType2>> type2 = std::make_shared<ProtobufMessageType2>();
class derived : base
{
void takeThePointerAndDoSpecificStuff( std::shared_ptr<PubOrSub<SpecificProtobufMessage>>) override
{
// check type and bind specific callback
}
}
One solution could be casting shared_ptr to base class but it is not possible because the protobuf message base class is pure virtual. Another solution is to cast the raw pointer and only transfer this one but I need the share_ptr reference count also in the method ( due to binding).
So I look further for a solution and std::any could be one but the problem here is that c++11 not have a std::any (sure could use boost but I try to avoid that).
So now I'm out of ideas how to solve the problem but perhaps you have one and can help me.
Thank you for any answer in advance.
One solution could be casting shared_ptr to base class but it is not possible because the protobuf message base class is pure virtual
That's simply not true. You can have shared pointers to abstract bases just fine:
Live On Coliru
#include <memory>
#include <iostream>
struct Base {
virtual ~Base() = default;
virtual void foo() const = 0;
};
struct D1 : Base { virtual void foo() const override { std::cout << __PRETTY_FUNCTION__ << "\n"; } };
struct D2 : Base { virtual void foo() const override { std::cout << __PRETTY_FUNCTION__ << "\n"; } };
int main() {
std::shared_ptr<Base> b = std::make_shared<D1>();
std::shared_ptr<Base> c = std::make_shared<D2>();
b->foo();
c->foo();
}
Prints
virtual void D1::foo() const
virtual void D2::foo() const
More Ideas
Even in case you do not have a common base (or a base at all) you can still use shared_pointer. One particularly powerful idiom is to use shared_pointer<void>:
Live On Coliru
#include <memory>
#include <iostream>
struct D1 {
void foo() const { std::cout << __PRETTY_FUNCTION__ << "\n"; }
~D1() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
struct D2 {
void bar() const { std::cout << __PRETTY_FUNCTION__ << "\n"; }
~D2() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
int main() {
std::shared_ptr<void> b = std::make_shared<D1>();
std::shared_ptr<void> c = std::make_shared<D2>();
std::static_pointer_cast<D1>(b)->foo();
std::static_pointer_cast<D2>(c)->bar();
}
Prints
void D1::foo() const
void D2::bar() const
D2::~D2()
D1::~D1()
See: http://www.boost.org/doc/libs/1_66_0/libs/smart_ptr/doc/html/smart_ptr.html#techniques_using_shared_ptr_void_to_hold_an_arbitrary_object

Initialization list of temporary derived objects

Suppose I have class A and two derived classes, B and C, e.g.:
#include <iostream>
#include <list>
#include <string>
using namespace std;
class A {
public:
virtual void poke() const = 0;
virtual ~A() {};
};
class B : public A {
string _response;
public:
B(const string& response) : _response(response) {}
void poke () const {
cout << _response << endl;
}
};
class C : public A {
string _response;
public:
C(const string& response) : _response(response) {}
void poke () const {
cout << "Well, " << _response << endl;
}
};
Can I somehow initialize an std::list using the following initializer list: {B("Me"), C("and you")}, so that polymorphism works when I iterate over the list and call poke() (i.e., no slicing occurs)? I guess I need to define an std::list<Smth>, where Smth accepts temporary objects, has a copy constructor that does move semantics inside (because initialization lists seem to be doing copying and not moving), and supports smart pointers so I can iterate with it and do (*it)->poke(). Just for clarity, I want to be be able to write:
list<Smth> test {B("Me"), C("and you")};
for(auto it = test.begin(); it != test.end(); it++) {
(*it)->poke();
}
I was trying to find a simple solution but I got to the point where my program compiled but generated run time errors, and so I gave up at that point... Maybe somehow make a unique pointer out of a temporary object? Or can I use && somehow?
For polymorphism, you need a reference or a pointer. Both will become dangling as soon as the sentence ends, because even if you bound those objects to them somehow, you bound them to temporary objects.
The usual solution is to dynamically allocate and create the objects and holding them with pointers. This means something like the following (I also changed the loop to C++11 style, instead of using iterators directly):
std::list<std::unique_ptr<A>> test {
std::make_unique<B>("Me"), std::make_unique<C>("and you")};
for(const auto& p : test) {
p->poke();
}
Well, if I am willing to do extra copying of B and C and use a shared_ptr instead of a unique_ptr, then the following example works (I am not saying it is good programming style, but it does show the cost of having a convenient notation with initialization lists):
#include <iostream>
#include <list>
#include <memory>
#include <string>
using namespace std;
class A {
public:
virtual void poke() const = 0;
virtual ~A() {}
};
class B : public A {
string _response;
public:
B(const string& response) : _response(response) {}
void poke () const {
cout << _response << endl;
}
operator shared_ptr<A>() {
return make_shared<B>(*this);
}
};
class C : public A {
string _response;
public:
C(const string& response) : _response(response) {}
void poke () const {
cout << "Well, " << _response << endl;
}
operator shared_ptr<A>() {
return make_shared<C>(*this);
}
};
int main() {
list<shared_ptr<A>> test {B("Me"), C("and you")};
for(const auto& it : test) {
it->poke();
}
}

How to initialize constant string for multiple tests in google test?

I'm using google test and I have a cpp-file containing several tests. I would like to initialize a string with the current date and time when starting the first test. I would like to use this string in all other tests, too. How can I do this.
I've tried the following (m_string being a protected member of CnFirstTest), but it didn't work (since the constructor and SetUp will be called before each test):
CnFirstTest::CnFirstTest(void) {
m_string = currentDateTime();
}
void CnFirstTest::SetUp() {
}
TEST_F(CnFirstTest, Test1) {
// use m_string
}
TEST_F(CnFirstTest, Test2) {
// use m_string, too
}
You can use a gtest testing::Environment to achieve this:
#include <chrono>
#include <iostream>
#include "gtest/gtest.h"
std::string currentDateTime() {
return std::to_string(std::chrono::steady_clock::now().time_since_epoch().count());
}
class TestEnvironment : public ::testing::Environment {
public:
// Assume there's only going to be a single instance of this class, so we can just
// hold the timestamp as a const static local variable and expose it through a
// static member function
static std::string getStartTime() {
static const std::string timestamp = currentDateTime();
return timestamp;
}
// Initialise the timestamp.
virtual void SetUp() { getStartTime(); }
};
class CnFirstTest : public ::testing::Test {
protected:
virtual void SetUp() { m_string = currentDateTime(); }
std::string m_string;
};
TEST_F(CnFirstTest, Test1) {
std::cout << TestEnvironment::getStartTime() << std::endl;
std::cout << m_string << std::endl;
}
TEST_F(CnFirstTest, Test2) {
std::cout << TestEnvironment::getStartTime() << std::endl;
std::cout << m_string << std::endl;
}
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
// gtest takes ownership of the TestEnvironment ptr - we don't delete it.
::testing::AddGlobalTestEnvironment(new TestEnvironment);
return RUN_ALL_TESTS();
}

performing static cast from a non template base class to a templated derived class which has variadic template parameter (c++)

I wanted to store a vector of function pointers, each taking different no. of arguments in a class "Store". So, wrote a templated class "Func" that would store the function as a std::function and its arguments in a tuple.
I derived this "Func" class from a non-template base class "IFunc", so that i can store a vector of pointers to this base class in the class "Store".
template<typename... Args>
class Func : public IFunc
{
public:
std::function<void (Args...)> f;
std::tuple<Args...> args;
template <typename F,typename... Ar>
Func(F&& func,Ar&&... arg): f(std::forward<F>(func)),args(std::make_tuple(std::forward<Ar>(arg)...))
{
}
virtual ~NonMemfun()
{
}
//other methods to unpack the tuple and call the function
};
The IFunc class:
class IFunc
{
public:
Ifunc(){}
virtual ~Ifunc(){}
};
The Store class:
class Store
{
std::vector<Ifunc*> funcs;
public:
template<typename... Args,typename... Args2>
void registerfunc(std::string name,int runs,void(*f)(Args...),Args2&&... arg)
{
Func<Args2...>* sample = new Func<Args2...>(f,arg...);
Ifunc* fp = sample;
funcs.push_back(fp);
}
};
I want to iterate through the vector and call each function. To do that i need to do a static cast like this:
Func<>* der = static_cast<Func<>*>(funcs[0]);
When i try to do this, the cast doesn't happen properly. I cannot specify the template paramenters(variadics) since this class(Store) is not aware of them.
I am totally stuck at this place. Something is wrong with my design i guess. Can someone please suggest me a better way to do this. Thank you.
Rather than trying to do a cast from IFunc to Func<>, you should make a pure virtual function, Apply() in IFunc, which Func<> defines as apply(f, args...);. As you iterate over the vector of IFunc pointers, simply call IFunc->Apply(), which will dispatch to the Func<>::Apply() and do the actual apply.
I'm not much of a C++ programmer, but I think you may find this useful.
I'm sure you know that templates are a compile time thing in C++ so your functions need to be known at build time.
With that said, if you do know your functions and you just want to map them to say a string command and then dynamically bind arguments from something like a stream then this code should help you. It is actually able to use a dynamic_cast to retrieve the command from the map.
this snippet is from a school project I did a while back that had a similar goal:
#include <map>
#include <string>
#include <sstream>
#include <tuple>
using namespace std;
class Shell {
class Command {
public:
virtual ~Command() {};
virtual void executeWithArgStream(Shell*, istream& s)=0;
};
template <typename... ArgTypes>
class ShellCommand : public Command {
private:
// FIXME: its probably more apropriate for FuncType to return an int for exit code...
typedef function<void(Shell*, ArgTypes...)> FuncType;
FuncType _f;
tuple<ArgTypes...> args;
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { typedef seq<Is...> type; };
template<size_t I = 0, class ...P>
typename std::enable_if<I == sizeof...(P)>::type
// template for functions with no arguments
parseArgs(istream& is, std::tuple<P...> &) {}
template<size_t I = 0, class ...P>
typename std::enable_if<I < sizeof...(P)>::type
parseArgs(istream& is, std::tuple<P...> & parts) {
// this is the magic bit that takes a tuple of pointers (representing the command arguments)
// created at compile time and creates new instances of each argument type and populates it from
// the given input stream :D
auto& part = std::get<I>(args);
// hmmm should we delete or recycle...
delete part;
part = new typeof(*part);
is >> *part;
parseArgs<I + 1>(is, parts);
}
template<int ...S>
void callFunc(Shell* shell, seq<S...>) {
_f(shell, get<S>(args) ...);
}
public:
static constexpr size_t numArgs = sizeof...(ArgTypes);
ShellCommand(FuncType f) : _f(f) {};
void operator()(Shell* shell, ArgTypes... args) {
_f(shell, args...);
};
void executeWithArgStream(Shell* shell, istream& s)
{
parseArgs(s, args);
callFunc(shell, typename gen_seq<sizeof...(ArgTypes)>::type());
};
};
private:
typedef shared_ptr<Command> CommandPtr;
typedef map<string, CommandPtr> FMap;
FMap _cmdMap;
ostream& _out;
istream& _in;
public:
Shell(istream& is = cin, ostream& os = cout)
: _out(os), _in(is)
{
// populate
_cmdMap.insert(pair<string, CommandPtr>("chdir", make_shared<ShellCommand<string*>>(&Shell::chdir)));
_cmdMap.insert(pair<string, CommandPtr>("list", make_shared<ShellCommand<>>(&Shell::list)));
_cmdMap.insert(pair<string, CommandPtr>("count", make_shared<ShellCommand<>>(&Shell::count)));
};
int run();
// FIXME: its probably more apropriate for execute to return an int for exit code...
template <typename... ArgTypes>
void execute(string& command, ArgTypes... args);
void executeWithArgStream(string& command, istream& istr);
// shell commands:
// any command parameters must be done as a pointer!
// the magic that parses string arguments into real types depends on it!
void list() {
list command
};
void chdir(string* dir) {
// chdir command
};
void count() {
// count command
};
};
template <typename... ArgTypes>
void Shell::execute(string& command, ArgTypes... args)
{
typedef ShellCommand<ArgTypes...> CommandType;
CommandType* c = dynamic_cast<CommandType*>(_cmdMap[command].get());
// TODO: neeed to diferentiate between invalid commands and some kind of dynamic_cast failure
if (c) {
(*c)(this, args...);
} else {
// dynamic cast failure
throw runtime_error("Broken Implementation for:" + command);
}
}
void Shell::executeWithArgStream(string& command, istream& istr)
{
Command* c = _cmdMap[command].get();
if (c) {
c->executeWithArgStream(this, istr);
} else {
throw runtime_error("Invalid Shell Command: " + command);
}
}
int Shell::run()
{
do {
string cmd, argString;
_out << _currentDir->name() << "> ";
_in.clear();
_in >> cmd;
if (cmd == "q") {
return 0;
}
if (_in.peek() == ' ')
_in.ignore(1, ' ');
getline(cin, argString);
if (_cmdMap[cmd]) {
try {
if (argString.length()) {
istringstream s(argString);
executeWithArgStream(cmd, s);
} else {
execute(cmd);
}
} catch (runtime_error& e) {
_out << e.what() << endl;
}
} else {
_out << "unrecognized command: " << cmd << endl;
}
} while (true);
}
int main(int argc, const char * argv[])
{
// start the interactive "shell"
Shell shell();
return shell.run();
}

Resources