I have two classes with inheritance. I want to allow the classes to store their function in one map. How can I create the find function by the key? And will the inheritance of the function work (MyClass_2 does not have its own doSmth() function, it should add the doSmth() from MyClass)? My attempt is below.:
template<class T>
class Class1
{
typedef void(T::*MyFunction)();
map<string, MyFunction> functionMap;
public:
void addFunc(string funcName, MyFunction function) {
functionMap.insert(pair<string, MyFunction>(funcName, function));
}
bool findFunc(string key) {
typename map<string, MyFunction>::iterator it;
it = functionMap.find(key.c_str());
}
};
class MyClass {
Class1<MyClass> class1;
void addFunc() {
class1.addFunc("Func1", &MyClass::doSmth);
}
void findAndCallFunc(string key) {
class1.findFunc(key);
}
void doSmth();
};
class MyClass_2: MyClass {
Class1<MyClass_2> class1;
void addFunc() {
class1.addFunc("Func1", &MyClass_2::doSmth);
}
}
EDIT: I tested my programm. It works. My problem is that if I call fundAndCallFunc from an object of MyClass_2. It takes not the class1 of MyClass_2, but class1 of MyClass.
What should I change?
As Chris says, your findFunc should return the actual function:
MyFunction findFunc(string key)
{
const map<string, MyFunction>::const_iterator it = functionMap.find(key);
return it == functionMap.end() ? NULL : it->second;
}
Further, if you only store the function pointer to a member function, you lose track of the actual object (so you could just make your map static!). Perhaps you should also store the this pointer of the object, i.e. make your map like this:
std::map<std::string, std::pair<T*, MyFunction> > functionMap;
In addFunc you would say
functionMap.insert(std::make_pair(funcName, std::make_pair(this, function)));
Usage: Suppose it = functionMap.find("key"). Then you could say:
MyClass * const p = it->second.first;
MyFunction f = it->second.second;
p->*f(); // invoke -- yes, it's operator->*() in action
You have two immediately obvious problems here:
your findFunc method just looks up the function, it doesn't do anything with it (attempt to call it or return the method pointer), and its declared as returning bool rather than MyFunction -- not sure what you want it to do
your doSmth method is private in MyClass, so you can't access it in MyClass_2. You'll need to make it protected or public.
Related
I have a very simple C++ lookup table for dispatching commands:
template <class T> Action* CreateAction(Command *c)
{
return new T(c);
}
typedef Action* CreateActionFunc(Command *c);
typedef struct ActionTable {
string name;
CreateActionFunc *func;
} ActionTableEntry;
vector<ActionTableEntry> GlobalActionTable = {
{ "quit" , &CreateAction<DoQuit> },
};
This works fine, but I would rather have my CreateAction function construct the new object on the stack and return it by value. But when I write this:
template <class T> T CreateAction(Command *c)
{
return T(c);
}
typedef Action CreateActionFunc(Command *c);
Then the program will no longer compile. First I get an error that an abstract class cannot be instantiated (on the typedef line) and also an error that the initialization list for the table doesn't match the type of the vector.
There is a very similar question here but every answer uses new in the factory methods, which is explicitly what I'm trying to avoid. How can this be done?
You can't use polymorphism with objects by value.
Need to be pointers or reference.
I'm guessing here you have an Action interface (so an abstract class), so you can't create an object of this dynamic type. All you can do is send a pointer of type Action with a dynamic type of a Derived Class (so what you are already doing i assume).
You could create a value object of a derived type on the stack and return a reference on the Base class and still use polymorphism, but then you'll need to address the lifetime of the Derived object problem.
The Action sub class has more information than the Action class itself - pointers to a table of it's member function, data members etc. There's not enough memory to hold this information if you return by value. Something called slicing would occur.
This answer explains it better.
How about doing something like this instead:
class Action {
void do_something(Command& params) = 0;
};
class SayHello {
void do_something(Command& params) { std::cout << "Hi!" << std::endl; }
}
class SayBye {
void do_something(Command& params) { std::cout << "Goodbye." << std::endl; }
}
.....
SayHello hello;
SayBye bye;
Quit quit;
std::map<string, Action&> action_table = {
{"hello", hello},
{"bye", bye},
{"quit", quit},
};
....
Action& getAction(Command* command) {
...;
return action_from_map;
}
This creates the action once, and returns them by reference.
What about something simple like this?
std::map<string, std::function<void(CommandArgs const&)>> action_table =
{
{"hello", [](CommandArgs const& args) { /* do something */ }},
};
I'm trying to implement a superclass in c++ that would implement one method:
-void setValueForKey(void *value, string key);
all this method would have to do is to set the value of a property associated with a given key to the new value.
This would be easy in a language that implements introspection mechanisms; as far as I know C++ doesn't.
In order to accomplish this I created another method:
void registerKeyForProperty(void *propertyPtr, string key);
all this method does is it stores in and internal map a pointer to a property associated with a given key, so all my subclasses would call this for every property they declare and I would have a way of setting values for properties without necessity to use the setters.(That's what I need!) (I explain why at the end of the post...)
for this second function I have the following implementation:
void registerKeyForProperty(void *propertyPtr, string key){
_keysDictionary->insert(pair<string,void*>(key,property));
}
where _keysDictionary is a stl map.
for the first one I have the following implementation:
void ConstructableObject::setValueForKey(void* value, string key) {
map<string,void *>::iterator it=_keysDictionary->find(key);
if(it==_keysDictionary->end()){return;}//just return if there is nothing for that key
void *property=it->second;
(*property)=value;
}
the problem is the last line is not legal C++ because ofcourse I cannot just deference that void*.
My questions are:
Is there any other way of implementing the desired functionality?
Is there a "legal" way of doing this the way I am doing it? (I cannot simply use a reinterpret_cast cause I don't know what to cast to...)
Why this:
I need to parse and xml file that has some information about some objects. I'll be using TinyXML and therefore I'll have the atribute names for the objects and their values. That would be how I would like to use it:
MyClass obj();//the constructor would call setValueForKey(...,...) for every property so all are now registered
for every attribute{
obj.setValueForKey(attribute.value,attribute.name);
}
//all properties should be set now
If the key exists, why not simply do
_keysDictionary[key] = value;
Or if you want to use the iterator
it->second = value;
It could be done with using of the type awareness techniques and for example The Memento Pattern is one of choices. The following code could be extended with the some macro stuff that generating the unique keys based on the attribute pointer signature:
class introspection
{
public:
template <typename Class, typename Member>
void registerKey(std::string key, Member Class::*memberPointee, Class* classPointee)
{
typedef member_setter<Class, Member> hold_member_pointer;
base_setter* setter = new hold_member_pointer(memberPointee, classPointee);
keys.insert(std::make_pair(key, setter));
}
template <typename Value>
void setValue(std::string key, Value value)
{
if ( keys.count(key) > 0 )
{
keys[key]->set(value);
}
else
{
throw std::logic_error("no such key");
}
}
private:
struct base_setter
{
virtual void set(boost::any value) = 0;
}; // struct base_setter
template <typename Class, typename Member>
struct member_setter : base_setter
{
member_setter(Member Class::*memberPointee, Class* classPointee)
: memberPointee(memberPointee)
, classPointee(classPointee) {}
void set(boost::any value) override
{
Member newValue = boost::any_cast<Member>(value);
classPointee->*memberPointee = newValue;
}
Member Class::*memberPointee;
Class* classPointee;
}; // struct member_setter
std::map<std::string, base_setter*> keys;
}; // class introspection
struct Data
{
int value;
}; // struct Data
int main()
{
introspection i;
Data d;
d.value = 100;
i.registerKey("value", &Data::value, &d);
i.setValue("value", 200); // OK
i.setValue("value", "not valid"); // bad_any_cast
}
The one thing that could be (not so easily) improved here is provide the compile-time type check for setValue, instead of runtime any_cast casting.
Make setValueForKey be a templated function instead of a function that accepts a void pointer. That way, you can know about the type information of the property long enough to create a templated setter
class BaseSetter
{
public:
virtual void set(void* inValue) = 0;
}
template <typename T>
class SpecializedSetter
{
public:
SpecializedSetter(T* inMyValue)
: mValue(inValue)
{ }
virtual void set(void* inValue)
{
*mValue = *reinterpret_cast<T*>(inValue);
}
private:
T* mValue;
}
template <typename T>
void registerKeyForProperty(T* inValue, string inKey)
{
registerSetterForProperty(new SpecificSetter<T>(inValue), inKey);
}
This, however, assumes inValue is a pointer to the same type of data as the value on the class. To make that safe, consider boost::any or defining some other type which contains the type information from the XML file and using that rather than void*
how to remove function that bound to member function of this object :
std::vector<std::function<void(int)>> callbacks;
class MyClass {
public:
MyClass() {
callbacks.push_back(
std::bind(&MyClass::myFunc,this,std::placeholders::_1)
);
}
~MyClass() {
auto it = std::remove_if( std::begin(callbacks),
std::end(callbacks),
[&](std::function<void(int)>& f) {
return // <-- this is my question
// true (remove) if f is bound to member function
// of this
});
callbacks.erase(it,std::end(callbacks));
}
void myFunc(int param){...}
};
typedef decltype(std::bind(&MyClass::myFunc,this,std::placeholders::_1)) bound_type;
auto it = std::remove_if( std::begin(callbacks),
std::end(callbacks),
[](const std::function<void(int)>& f) {
return f.target<bound_type>() != nullptr;
});
The member function template std::function::target<T> returns a pointer to the target object if it is of type T, otherwise it returns null. So you just need to be able to name the type of the target object, which you can get from decltype. Pretty simple really :-)
N.B. that will remove any callbacks of that type, not only ones that have bound the this pointer for the specific object being destroyed. If you are trying to prevent invoking callbacks on an object after it has been destroyed and have no possible way to identify which elements of the vector refer to which objects, you could consider putting a shared_ptr in your class, then storing a weak_ptr to it in the callback, which can be used to detect if the object has been destroyed:
class MyClass
{
struct NullDeleter { void operator()(void*) const { } };
std::shared_ptr<MyClass> sp;
static void safe_invoke(void (MyClass::*f)(int), const std::weak_ptr<MyClass>& wp, int i)
{
if (std::shared_ptr<MyClass> safe_this = wp.lock())
(safe_this.get()->*f)(i);
}
public:
MyClass() : sp(this, NullDeleter()) {
callbacks.push_back(
std::bind(safe_invoke, &MyClass::myFunc ,std::weak_ptr<MyClass>(sp),
std::placeholders::_1)
);
};
This wraps the call to the member function with the invoke function that converts the weak_ptr to a shared_ptr before calling the member function. If the object has been destroyed the shared_ptr will be empty, so the function does nothing. This doesn't actually remove the callback when it becomes invalid, but does make it safe to call.
You can't in the general case without a buttload of extra work. Type erasure clears this information from the object, and std::function does not expose this information directly.
Your specific example may only have one member function that could be the candidate to remove, but what about a class with 5 members that could be stored as callbacks? You'll need to test for all of them, and it's also possible to bind member functions using a lambda, which is pretty much undetectable.
Here's one solution if:
all callbacks are registered from within MyClass
the container is amended to store extra information
you're willing to do all the extra bookkeeping
std::vector<std::pair<std::function<void(int)>, void*>> callbacks;
class MyClass{
static unsigned const num_possible_callbacks = 2; // keep updated
std::array<std::type_info const*, num_possible_callbacks> _infos;
unsigned _next_info;
// adds type_info and passes through
template<class T>
T const& add_info(T const& bound){
if(_next_info == num_possible_callbacks)
throw "oh shi...!"; // something went out of sync
_infos[_next_info++] = &typeid(T);
return bound;
}
public:
MyClass() : _next_info(0){
using std::placeholders::_1;
callbacks.push_back(std::make_pair(
add_info(std::bind(&MyClass::myFunc, this, _1)),
(void*)this));
callbacks.push_back(std::make_pair(
add_info([this](int i){ return myOtherFunc(i, 0.5); }),
(void*)this));
}
~MyClass(){
using std::placeholders::_1;
callbacks.erase(std::remove_if(callbacks.begin(), callbacks.end(),
[&](std::pair<std::function<void(int)>, void*> const& p) -> bool{
if(p.second != (void*)this)
return false;
auto const& f = p.first;
for(unsigned i = 0; i < _infos.size(); ++i)
if(_infos[i] == &f.target_type())
return true;
return false;
}), callbacks.end());
}
void myFunc(int param){ /* ... */ }
void myOtherFunc(int param1, double param2){ /* ... */ }
};
Live example on Ideone.
I once needed to do something like this and I solved it by storing a vector of shared pointers of objects in the class that contain the function and remove the function from the vector by value when they are destroyed, which also makes this automatic.
I need a table that maps codes to C++ member functions. Suppose we have this class:
class foo
{
bool one() const;
bool two() const;
bool call(char*) const;
};
What I want is a table like this:
{
{ “somestring”, one },
{ ”otherstring”, two }
};
So that if I have a foo object f, f.call(”somestring”) would look up “somestring” in the table, call the one() member function, and return the result.
All of the called functions have identical prototypes, i.e., they are const, take no parameters, and return bool.
Is this possible? How?
Yes, it's possible, using pointer to member syntax.
Using the prototypes you supplied, the map would be.
std::map< std::string, bool( foo::*)() const>
It would be called with this syntax
this->*my_map["somestring"]();
That odd-looking ->* operator is for pointer to member functions, which can have some odd considerations, due to inheritance. (It's not just a raw address, as -> would expect)
Since you only need to store members of the same class, with the same arguments and return types, you can use pointer-to-member-functions:
bool foo::call(char const * name) const {
static std::map<std::string, bool (foo::*)() const> table
{
{"one", &foo::one},
{"two", &foo::two}
};
auto entry = table.find(name);
if (entry != table.end()) {
return (this->*(entry->second))();
} else {
return false;
}
}
That uses the new initialisation syntax of C++11. If your compiler doesn't support it, there are various other options. You could initialise the map with a static function:
typedef std::map<std::string, bool (foo::*)() const> table_type;
static table_type table = make_table();
static table_type make_table() {
table_type table;
table["one"] = &foo::one;
table["two"] = &foo::two;
return table;
}
or you could use Boost.Assignment:
static std::map<std::string, bool (foo::*)() const> table =
boost::assign::map_list_of
("one", &foo::one)
("two", &foo::two);
or you could use an array, and find the entry with std::find_if (or a simple for loop if your library doesn't have that yet), or std::binary_search if you make sure the array is sorted.
Yes.
struct foo_method
{
std::string name;
bool (foo::*pfun)() const;
};
foo_method methodTable[] =
{
{ “somestring”, &foo::one },
{ ”otherstring”, &foo::one }
};
void foo::call(const char* name) const
{
size_t size = sizeof(methodTable)/sizeof(*methodTable);
for(size_t i = 0 ; i < size ; ++i)
{
if ( methodTable[i].name == name )
{
bool (foo::*pfun)() const = methodTable[i].pfun;
(this->*pfun)(); //invoke
}
}
}
I would go with boost::function with std::map. Concretely, something like this :
typedef boost::function<bool()> MyFunc;
typedef std::map<std::string, MyFunc> MyFuncMap;
Then, given an instance of MyFuncMap, you could just do map["something"](). Then you could wrap that in a class that overloads operator(). You could use function pointers/references, but I prefer using boost::function because it allows me to bind pointers to member functions (using boost::bind) or use other function objects. You can also test boost::function in conditionals as you would with regular function pointers.
Here is the relevant documentation :
Boost.Function
Boost.Bind
Good luck!
Edit: Regarding your question about the const member and boost::function, here's an example :
#include <boost/function.hpp>
#include <boost/bind.hpp>
typedef boost::function<bool ()> FuncPtr;
struct Test
{
bool test() const
{
std::cout << "yay" << std::endl;
}
};
int main(int argc, char **argv)
{
Test t;
FuncPtr ptr = boost::bind(&Test::test, &t);
ptr();
}
I'd just like to add that a pointer to a member function is meaningless without having an instance of a class on which to call it. The situation you've described accounts for this (and I think you know this), however in other situations, it may be necessary to encapsulate the function pointer with a pointer or reference to the instance to which it corresponds in some sort of functor construct.
i was wondering if there was a way to do this in C++?
void func1(const std::string& s)
{
std::cout << s << std::endl;
}
void func2(int me)
{
std::cout << me << std::endl;
}
int main()
{
std::map<std::string, boost::function< ??? > > a_map;
a_map["func1"] = &func1;
a_map["func1"]("HELLO");
}
Is there any way to do what i have above using boost function and a map?
There are ways to store the functions, the problem is, in order to be able to call the function with the desired argument you'd have to know the calling signature of the function anyways, and if you have that information, you might as well use separate maps, or use a more complicated object than boost::function.
If you're willing to do a bit of work and have a finite number of signatures, you could just do something like this:
class MultiFunc
{
protected:
MultiFunc() {}
public:
typedef void (*stringFunc)(const std::string&);
typedef void (*intFunc)(int);
static MultiFunc *Create(stringFunc function);
static MultiFunc *Create(intFunc function);
virtual void operator()(const string &) { throw exception(); }
virtual void operator()(int) { throw exception(); }
virtual ~MultiFunc();
};
class MultiFuncString : public MultiFunc
{
private:
stringFunc Function;
public:
MultiFuncString(stringFunc function) : Function(function) {}
virtual void operator()(const string &arg) { Function(arg); }
};
class MultiFuncInt : public MultiFunc
{
private:
intFunc Function;
public:
MultiFuncInt(intFunc function) : Function(function) {}
virtual void operator()(int arg) { Function(arg); }
};
MultiFunc *MultiFunc::Create(MultiFunc::stringFunc function)
{
return new MultiFuncString(function);
}
MultiFunc *MultiFunc::Create(MultiFunc::intFunc function)
{
return new MultiFuncInt(function);
}
void func1(const std::string& s)
{
std::cout << s << std::endl;
}
void func2(int me)
{
std::cout << me << std::endl;
}
int main()
{
map<string, MultiFunc *> a_map;
a_map["func1"] = MultiFunc::Create(&func1);
(*a_map["func1"])("Hello");
a_map["func2"] = MultiFunc::Create(&func2);
(*a_map["func2"])(3);
// Remember to delete the MultiFunc object, or use smart pointers.
}
This outputs:
Hello
3
Unfortunately, you can't make templated virtual functions or you easily generalize this all.
You probably can't use the std::map since it is a homogenous container. Try, something like boost::variant (they support the visitor pattern) or boost::tuple
What you are trying to do sounds a little weird. Normally, you would have a container be a collection of abstract types or objects or functions with the same signature. Otherwise, how would you know how to call the function when you are iterating the container? I like to make the container a collection of function objects with a known signature, then use Boost.Bind to store closures that call the function with additional arguments.
For example:
typedef boost::function<void, void> Function;
typedef std::map<std::string, Function> Functions;
Functions functions:
void foo()
{
...
}
functions["foo"] = foo;
void bar(std::string &s)
{
...
}
// binds the value "hello" to the s parameter
functions["bar"] = boost::bind(bar, "hello");
read this link below. It talks about using boost::bind to store the function pointers in std::map
http://www.gamedev.net/community/forums/topic.asp?topic_id=526381&whichpage=1�
store interfaces:
struct IStringData
{
virtual std::string get() const = 0;
virtual ~IStringData() {}
};
and make implementaions, one will just hold string value, other implementation will store functor, maybe you will have other implementations in future.
No. You can't. Since boost::function isn't polymorphic, it breaks down there. (It takes a fixed set of argument types.)
There was talk about work in that direction on the boost mail-list, though, so search the archives and see if there is some code you could youse.
A workaround would be to use boost::function but then you need to add to the map not your real functions (i.e. func1/func2) but dispatch functions that extracts the type from the any-container and calls the real function. (And bails if it's wrong, just as in any dynamic langugage.)