c++ void* to parameter to a function - c++

I have this function in some library:
class myConsole
{
void addCommand( std::string command, void* fn );
...
}
and in my class I have this function:
void myApp::TestFn( const std::vector<std::string> & args )
{
// do something
}
in the same class I call this:
void myApp::initApp( )
{
myConsole::getSingleton( ).addCommand( "FirstTest", &myApp::TestFn );
}
but this gives me this error:
error c2664 cannot convert parameter 2 from 'void(__thiscall
myApp::*)(const std::vector<_Ty>&)' to 'void *'
how can I solve this?
thanks in advance!

You can't solve this. You can't reliably cast a function pointer to void * and back.
(I suggest you redesign the program and stay clear of void*; there's no real need for it in C++.)

The problem here is that you are trying to pass a class method as it were a void * pointer. This cannot be done.
The right way of doing this is by using templates for the void addCommand (std::string, void *) method. Something like
class myConsole {
template <typename T>
void addCommand( std::string command, T f);
};
struct Callback {
myApp &app;
Callback (myApp &a) : app(a) {
}
void operator() (const std::vector<std::string> &args) {
app.TestFn(args);
}
};
void myApp::initApp( )
{
myConsole::getSingleton( ).addCommand( "FirstTest", Callback(*this) );
}
This gives you the callback principle in C++, but I think you need something more flexible than this solution, since you actually want to choose automatically the command that will be executed by the callback (in this case TestFn).

You should avoid void*, especially when trying to use function pointers. I'm going to assume that you are looking only at member-function pointers in the myApp class, and that you are only interested in member-function pointers which take const std::vector<std::string> &args as an argument. This typedef will create the appropriate type and call it MemFunType
typedef void (myApp :: * MemFunType) (const std::vector<std::string> &);
Here is a complete example (on ideone), where there are two different member-functions you may be interested in, TestFn and TestFnBackwards. This example probably isn't very useful, but it gives some examples of member-function pointers.
#include<iostream>
#include<vector>
using namespace std;
struct myApp;
struct myConsole
{
typedef void (myApp :: * MemFunType) (const std::vector<std::string> &);
void addCommand( std::string command, MemFunType fn );
};
struct myApp {
void TestFn( const std::vector<std::string> & args ) {
cout << " TestFn" << endl;
for(std :: vector<std::string> :: const_iterator i = args.begin(); i!=args.end(); i++) {
cout << *i << endl;
}
}
void TestFnBackwards( const std::vector<std::string> & args ) {
cout << " TestFnBackwards" << endl;
for(std :: vector<std::string> :: const_reverse_iterator i = args.rbegin(); i!=args.rend(); i++) {
cout << *i << endl;
}
}
static myApp & getSingleton();
} ma;
myApp& myApp :: getSingleton() {
return ma;
}
void myConsole :: addCommand( std::string , MemFunType fn ) {
vector<string> words;
words.push_back("hello");
words.push_back("world");
myApp &ma = myApp :: getSingleton();
(ma.*fn)(words); // execute the member on the singleton object, using the words as the argument.
}
int main() {
myConsole m;
m.addCommand( "FirstTest", &myApp::TestFn );
m.addCommand( "FirstTest", &myApp::TestFnBackwards );
}

Related

c++ callbacks to another member function

I have a question on callbacks. Previously, I am associating my callbacks to a class Q
class Q{
using Callback = std::function<void(char*, int)>;
Q:Q();
Q:~Q();
void Q::RegisterCB(Callback callbackfunc)
{
callback_func = callbackfunc;
}
void Q:someEvent()
{
callback_func();
}
};
void handleCallback( char*, int)
{
// perform some routine
}
// from my main file
int main()
{
Q q;
q.RegisterCB(&handleCallback);
}
It works well for me. However, when I need to transfer the handleCallback function to another class for cleaner code. I have problem with using same code
class R{
void R::handleCallback( char*, int)
{
// perform some routine
}
void R::someOp()
{
// q is some member variables of R
q.RegisterCB(&R::handleCallback, this);
}
};
However, i run into some problems of saying there is a "no matching function for call to .....". I thought it was just simply assigning from function name to class function name
May I have a hint to where I might go wrong?
Regards
&R::handleCallback has the type void (R::*)(char*, int), which is not convertible to std::function<void(char*, int)>.
Also, RegisterCB takes one argument, not two.
The most straightforward fix is to wrap the call in a lambda function,
q.RegisterCB([this](char* p, int x) { handleCallback(p, x); });
Example on how to use a lambda function to register a member function of an instance of R as event handler. (I replaced char* with string_view out of habit, it's not essential for this example). The use of "const" wherever you can is a recommendation.
#include <functional>
#include <string_view>
#include <iostream>
class Q
{
public:
// use const arguments, the callback is not supposed to change them
// just passing information on to callback
using callback_t = std::function<void(const std::string_view&, const int)>;
// initialize callback with a (lambda) function that does nothing
// this prevents the need for a check if callback has been set or not
// (Pattern : Null Strategy)
Q() :
m_callback_func( [](const std::string_view&,const int) {} )
{
}
~Q() = default;
void RegisterCallback(callback_t fn)
{
m_callback_func = fn;
}
void Event(const std::string_view& string, const int value)
{
m_callback_func(string,value);
}
private:
callback_t m_callback_func;
};
void handleCallback(const std::string_view& string, const int value)
{
std::cout << string << ", " << value << "\n";
}
class R
{
public:
void handleCallback(const std::string_view& string, const int value)
{
std::cout << string << ", " << value << "\n";
}
};
// from my main file
int main()
{
Q q1;
q1.RegisterCallback(handleCallback);
q1.Event("Hello", 42);
// to pass a callback to an instance of a class
// you can use a lambda function https://en.cppreference.com/w/cpp/language/lambda
R r;
Q q2;
q2.RegisterCallback([&r](const std::string_view& string, const int value)
{
r.handleCallback(string,value);
});
q2.Event("World",21);
return 0;
}

pass userData from callback-begin to callback-end

How to appropriately cache userData that is generated from user's callbackBegin() and send it to user's callbackEnd().
Simple version (No userData - demo)
I want to create a complex database that support callback. For MCVE, let's say it is MyArray.
Here is a simple array class that supports callback but no userData.
#include <iostream>
template<class Derived>class MyArray{ //library - I design it.
public: void push_back(int s){
static_cast<Derived*>(this)->callbackBegin(s);
//do something about array
static_cast<Derived*>(this)->callbackEnd(s);
}
//other fields / functions
};
class Callback : public MyArray<Callback>{ //user's class
public: void callbackBegin(int s){
std::cout<<"callbackBegin"<<std::endl;
}
public: void callbackEnd(int s){
std::cout<<"callbackEnd"<<std::endl;
}
};
int main() {
Callback c;
c.push_back(5); //print: callbackBegin callbackEnd
return 0;
}
It works correctly.
The next step : I want to pass some userData from Callback::callbackBegin() to Callback::callbackEnd().
For example, userData is a clock time when Callback::callbackBegin() is called.
My poor solution (void*& userdata : demo)
Here is my attempt to implement it :-
#include <iostream>
#include <time.h>
template<class Derived>class MyArray{
public: void push_back(int s){
void* userData=nullptr; //#
static_cast<Derived*>(this)->callbackBegin(s,userData); //# ugly
//do something about array
static_cast<Derived*>(this)->callbackEnd(s,userData); //# ugly
}
};
class Callback : public MyArray<Callback>{
public: void callbackBegin(int s,void*& userData){ //#
userData=new clock_t(clock()); //# danger
std::cout<<"callbackBegin"<<std::endl;
}
public: void callbackEnd(int s,void*& userData){ //#
clock_t* userDataTyped=static_cast<clock_t*>(userData);
clock_t clock2=clock();
clock_t different=clock2 - (*userDataTyped);
std::cout<<"callbackEnd time(second)="
<<((float)different)/CLOCKS_PER_SEC<<std::endl;
delete userDataTyped; //# danger
}
};
int main() {
Callback c;
c.push_back(5); //print: callbackBegin callbackEnd time(second)=8.5e-05
return 0;
}
It also works correctly, but I believe it is a bad design (at various #) :-
new/delete in 2 places : potential memory leaking.
Strong pointer is preferred, but I don't know how to.
static_cast<clock_t*>(userData) is code-smell, at least for me.
(minor issue) an extra ugly parameter void*&
Question: What are design patterns / C++ magic to avoid such issues, while make MyArray concise, easy to use, maintainable (i.e. not much worse than the Simple version)?
Other notes:
In real cases, <5% of user's callback classes need userData.
Thus, I feel very reluctant to add void&* as an extra parameter.
Clarify: (edited) The minority cases usually need different types of userData e.g. Callback1 need clock_t, Callback2 need std::string, etc.
Proposed solution should restrain from using std::function<> or virtual function, because the performance is a major concern here.
Thank.
Pass data through a void pointer is a good C solution but (IMHO) not a C++ (specially: not a C++11/c++14/C++17, with auto and std::tuple) good one.
So I suggest to return a value from callbackBegin() and pass the value as first argument to `callbackEnd(); something like
auto r = static_cast<Derived*>(this)->callbackBegin(s);
static_cast<Derived*>(this)->callbackEnd(r, s);
Observe (C++11 and newer magic) that using auto as type of the value returned by callbackBegin(), you can return different types from different `callbackBegin().
Bonus suggestion: be more generic in MyArray::push_back(): using variadic templates, there is no need of fix the number and the types of arguments received by callbackBack() and callbackEnd().
Using variadic templates you can modify push_back() as follows
template <typename ... Args>
void push_back (Args const & ... args)
{
auto r = static_cast<Derived*>(this)->callbackBegin(args...);
static_cast<Derived*>(this)->callbackEnd(r, args...);
}
The following is a full working example with two different callback classes (with different number of arguments and different return types)
#include <tuple>
#include <iostream>
template <typename derT>
struct myA
{
template <typename ... Args>
void push_back (Args const & ... args)
{
auto r = static_cast<derT*>(this)->callbackBegin(args...);
static_cast<derT*>(this)->callbackEnd(r, args...);
}
};
struct cb1 : public myA<cb1>
{
int callbackBegin (int s)
{ std::cout << "cb1 b" << std::endl; return s+5; }
void callbackEnd (int r, int s)
{ std::cout << "cb1 e -" << r << ", " << s << std::endl; }
};
struct cb2 : public myA<cb2>
{
std::tuple<std::string, int> callbackBegin (std::string const & name,
int num)
{ std::cout << "cb2 b" << std::endl; return {name+";", num+1}; }
void callbackEnd (std::tuple<std::string, int> const &,
std::string const & name, int num)
{ std::cout << "cb2 e -" << name << ", " << num << std::endl; }
};
int main ()
{
cb1 c1;
c1.push_back(5);
cb2 c2;
c2.push_back("string arg", 7);
return 0;
}
std::any would allow you to hold clock_t (or any other) object and do away with the void* pointers, however that's a C++17 concept and not yet widely available (although there are implementations such as boost::any).
In the meantime, your code may benefit from a little composition over inheritance, as array and callback are conceptually pretty different and don't seem to belong in the same inheritance hierarchy. So, preferring composition, the code might look something like:
template<class T> struct ICallback
{
virtual void callbackBegin(int s, std::unique_ptr<T>& p) = 0;
virtual void callbackEnd(int s, std::unique_ptr<T>& p) = 0;
};
template<class T> class MyArray
{
public:
MyArray(std::shared_ptr<ICallback<T>> cb) { callback = cb; }
void push_back(int s)
{
callback->callbackBegin(s, usrDataPtr);
//do something about array
callback->callbackEnd(s, usrDataPtr);
}
protected:
std::shared_ptr<ICallback<T>> callback;
std::unique_ptr<T> usrDataPtr;
};
class ClockCallback : public ICallback<clock_t>
{
public:
void callbackBegin(int s, std::unique_ptr<clock_t>& c){
c = std::make_unique<clock_t>(clock());
std::cout << "callbackBegin" << std::endl;
}
void callbackEnd(int s, std::unique_ptr<clock_t>& c){
clock_t clock2 = clock();
clock_t different = clock2 - (*c);
std::cout << "callbackEnd time(second)="
<< ((float)different) / CLOCKS_PER_SEC << std::endl;
}
};
int main() {
std::shared_ptr<ClockCallback> c = std::make_shared<ClockCallback>();
MyArray<clock_t> ma(c);
ma.push_back(7);
return 0;
}
You can use a smart pointer to avoid manually deleting your userData
std::unique_ptr<clock_t> userData;
pass it as a reference to your callbacks
void callbackBegin(int s, std::unique_ptr<clock_t> &userData)
and initialize it this way
userData = std::make_unique<clock_t>(clock())
The C++ magic you're asking about is a known as a virtual method. Virtual method is one of the C++ native ways to implement the callback:
class MyArray{
public:
void push_back(int s) {
const auto userData = callbackBegin(s); //# beautiful
//do something about array
callbackEnd(s, userData); //# beautiful
}
private:
virtual clock_t callbackBegin(int) const = 0;
virtual void callbackEnd(int, const clock_t&) const = 0;
};
class Callback : public MyArray{
clock_t callbackBegin(int s) const final {
std::cout<<"callbackBegin"<<std::endl;
return clock(); //# safe
}
void callbackEnd(int s,const clock_t& userData) const final { //#
const auto different = clock() - userDataTyped;
std::cout << "callbackEnd time(second)=";
std::cout << different/CLOCKS_PER_SEC << std::endl;
//# safe
}
};
Another way is to pass two callable objects to the MyArray ctor and using those objects in the push_back method. The callable objects shall store calls to the relevant class Callback methods. Use std::function to implement those callable objects.

How to work around C++ pointer-to-member function limitation

C++ has limited ability to use pointer-to-member functions. I need something that will allow me to dynamically choose a callback member function, in order to use the Visitor pattern of the XMLNode::Accept(XMLVisitor *visitor) method from the TinyXML2 library.
To use XMLNode::Accept(), I must call it with a class which implements the XMLVisitor interface. Hence:
typedef bool (*Callback)(string, string);
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
callback(e.Name(), e.GetText());
}
Callback callback;
}
This works fine if my caller is NOT an object which wants to use one of its own methods as a callback function (so that it can access class variables). For example, this works:
bool myCallBackFunc(string e, string v) {
cout << "Element " << e << " has value " << v << endl;
return true;
}
int main(...) {
tinyxml2::XMLDocument doc;
doc.LoadFile("somefile.xml");
MyVisitor visit;
visit.callback = myCallBackFunc;
doc.Accept(&visit);
}
However, in my use case, the parsing is done inside a method in a class. I have multiple applications which have similar but unique such classes. I'd like to use only one generic MyVisitor class, rather than have the visitor class have unique knowledge of the internals of each class which will call it.
Thus, it would be convenient if the callback function were a method in each calling class so that I can affect the internal state of the object instantiated from that calling class.
Top level: I have 5 server applications which talk to 5 different trading partners, who all send XML responses, but each is enough different that each server app has a class which is unique to that trading partner. I'm trying to follow good OO and DRY design, and avoid extra classes having unique knowledge while still doing basically the same work.
Here's the class method I want Accept() to call back.
ServiceClass::changeState(string elem, string value) {
// Logic which sets member vars based on element found and its value.
}
Here's the class method which will call Accept() to walk the XML:
ServiceClass::processResponse(string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
MyVisitor visit;
visit.callback = &changeState; // ERROR. Does not work.
visit.callback = &ServiceClass::changeState; // ERROR. Does not work.
doc.Accept(&visit);
}
What's a simple way to get what I want? I can imagine more classes with derived classes unique to each situation, but that seems extremely verbose and clumsy.
Note: In the interest of brevity, my sample code above has no error checking, no null checking and may even have minor errors (e.g. treating const char * as a string ;-).
Below is the std::bind(..) example for what you're trying to do in C++11. For earlier C++ versions you could use the boost::bind utilities.
Fix your MyVisitor::VisitExit(...) method to return a boolean, by the way.
The code is converting const char * to std::string. tinyxml2 does not guarantee that the char * arguments from Name() or GetText() are not null. In fact in my experience they will be null at some point. You should guard against this. For the sake of not modifying your example too much I've not protected against this possibility everywhere in the example.
typedef bool(*Callback)(string, string);
using namespace std;
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
// return callback(e.Name(), e.GetText());
return true;
}
Callback callback;
};
/** Typedef to hopefully save on confusing syntax later */
typedef std::function< bool(const char * element_name, const char * element_text) > visitor_fn;
class MyBoundVisitor : public tinyxml2::XMLVisitor {
public:
MyBoundVisitor(visitor_fn fn) : callback(fn) {}
bool VisitExit(const tinyxml2::XMLElement &e) {
return callback(e.Name() == nullptr ? "\0" : e.Name(), e.GetText() == nullptr ? "\0": e.GetText());
}
visitor_fn callback;
};
bool
myCallBackFunc(string e, string v) {
cout << "Element " << e << " has value " << v << endl;
return true;
}
int
main()
{
tinyxml2::XMLDocument doc;
doc.LoadFile("somefile.xml");
MyVisitor visit;
visit.callback = myCallBackFunc;
doc.Accept(&visit);
visitor_fn fn = myCallBackFunc; // copy your function pointer into the std::function<> type
MyBoundVisitor visit2(fn); // note: declare this outside the Accept(..) , do not use a temporary
doc.Accept(&visit2);
}
So from within the ServiceClass method you'd do:
ServiceClass::processResponse(string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
// presuming changeState(const char *, const char *) here
visitor_fn fn = std::bind(&ServiceClass::changeState,this,std::placeholders::_1,std::placeholders::_2);
MyBoundVisitor visit2(fn); // the method pointer is in the fn argument, together with the instance (*this) it is a method for.
doc.Accept(&visit);
}
You can use generics in order to support whichever callback you'd like.
I've tried to mock the classes of the library in order to give you a fully runnable example:
#include <string>
#include <iostream>
#include <functional>
class XmlNode {
public:
XmlNode(const std::string& n, const std::string t) : name(n), txt(t) {}
const std::string& Name() const { return name; }
const std::string& GetText() const { return txt; }
private:
std::string name;
std::string txt;
};
class XMLVisitor {
public:
virtual void VisitExit(const XmlNode& node) = 0;
virtual ~XMLVisitor() {}
};
template<typename T>
class MyVisitor : XMLVisitor {
public:
MyVisitor() {}
void myInnerPrint(const XmlNode& node) {
std::cout << "MyVisitor::myInnerPrint" << std::endl;
std::cout << "node.Name(): " << node.Name() << std::endl;
std::cout << "node.GetText(): " << node.GetText() << std::endl;
}
void SetCallback(T newCallback) {
callback = newCallback;
}
virtual void VisitExit(const XmlNode& node) {
callback(node);
}
T callback;
};
int main() {
XmlNode node("In", "Member");
MyVisitor<std::function<void(const XmlNode&)>> myVisitor;
auto boundCall =
[&myVisitor](const XmlNode& node) -> void {
myVisitor.myInnerPrint(node);
};
myVisitor.SetCallback(boundCall);
myVisitor.VisitExit(node);
return 0;
}
First define a template and a helper function:
namespace detail {
template<typename F>
struct xml_visitor : tinyxml2::XMLVisitor {
xml_visitor(F&& f) : f_(std::move(f)) {}
virtual void VisitExit(const tinyxml2::XMLElement &e) {
f_(e);
}
private:
F f_;
};
}
template<class F>
auto make_xml_visitor(F&& f)
{
return detail::xml_visitor<std::decay_t<F>>(std::forward<F>(f));
}
Then use the helper function to construct a custom visitor from a lambda which captures this:
void ServiceClass::processResponse(std::string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
auto visit = make_xml_visitor([this](const auto& elem)
{
this->changeState(elem.Name(), elem.GetText);
});
doc.Accept(std::addressof(visit));
}
The rule is that a function pointer must always accept a void * which is passed in to the module which calls it, and passed back. Or use a lambda which is the same thing with some of the machinery automated for you. (The void * is the "closure").
So
typedef bool (*Callback)(string, string, void *context);
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
callback(e.Name(), e.GetText(), contextptr);
}
Callback callback;
void *contextptr;
}
bool myCallBackFunc(string e, string v, void *context) {
ServiceClass *service = (ServiceClass *) context;
cout << "Element " << e << " has value " << v << endl;
service->ChangeState(e, v);
return true;
}

Can this be solved with a template specialization, if not then how?

I have several "resources" in my code base. All of them are classes and share the same interface except one class, the ShaderProgram is different in just one way, it needs two strings for files names of the vertex and fragment files.
I have a template class called ResourceManager that handles all these resource except the shader one because it needs two files and the others need one, can I solve this with a template specialization? It needs to be that ResourceManager sees GetOrLoadFromFile( string, string ) and not (string) versions, while the others have the opposite, they see (string) and not (string, string). Also AttemptLoad needs the treatment too. How can I make a solution for this please include code, I have never done template specializations before.
template < class ResType > class ResourceManager
{
public:
ResourceManager(void);
~ResourceManager(void);
SmartPointer<ResType> GetOrLoadFromFile( const std::string & fileName );
//weak_ptr<ResType> GetResourceFromID( ResourceID & resID );
void DestroyResources();
void ReleaseResources();
void ReloadResources();
protected:
private:
SmartPointer<ResType> AttemptLoad( const std::string & fileName );
std::unordered_map<string, SmartPointer<ResType> > mResMap;
};
// Relevant methods ( SNIPPED )
template < class ResType> SmartPointer<ResType> ResourceManager<ResType>::GetOrLoadFromFile( const std::string & fileName )
{
if ( !mResMap.empty() )
{
auto index = mResMap.begin();
auto end = mResMap.end();
while ( index != end )
{
if ( index->first == fileName )
{
return index->second;
}
++index;
}
}
return AttemptLoad(fileName);
}
template < class ResType > SmartPointer<ResType> ResourceManager<ResType>::AttemptLoad( const std::string & fileName )
{
SmartPointer<ResType> pRes( new ResType() );
if ( pRes->LoadFromFile( fileName ) )
{
mResMap.insert( std::make_pair( fileName, pRes ) );
return pRes;
}
else
{
LogFailure("Failed to load resource file " + fileName)
return SmartPointer<ResType>(nullptr);
}
}
If both classes are under your control I would suggest a different solution. Why don't you change the AttempLoad method into something like
SmartPointer<ResType> AttemptLoad( const LoadConfiguration &p_loadConfiguration );
Where
class LoadConfiguration
{
public:
std::string FirstFileName;
};
and
class ExtendedLoadConfiguration : public LoadConfiguration
{
public:
std::string SecondFileName;
};
you could then always work with LoadConfiguration and each AttemptLoad would be able to take what he needs. Adding new arguments will be easy, it's less code with the same signature and you wouldn't have to work with template specialization.
The idea behind templates is that you known your types before the execution times, i.e., at compilation time. If this is true, than what you are trying to do is an overloading using templates. So, bellow I just put a generic code, that you can adapt to your code, that do overloading at compilation time.
Note that, to avoid writing code twice, every common methods are put in base class and let to the derived class only the ones that diverges.
#include <memory>
#include <string>
#include <iostream>
using namespace std;
class Base
{
// put common codes here
};
template <typename ResType>
class ResourceManager : public Base
{
public:
unique_ptr<ResType> GetorLoad(const string &f) { cout << f << endl; return 0;}
};
// Specilizing class ResourceManager for string type
template <>
class ResourceManager<string> : public Base
{
public:
unique_ptr<string> GetorLoad(const string &f1, const string &f2) {cout << f1 << f2 << endl; return 0;}
};
int main()
{
ResourceManager<int> i;
ResourceManager<string> s;
i.GetorLoad("int");
s.GetorLoad("string", "string");
}
PS. To compile and test this example, you need to use '--std=c++11' flag from gcc or clang++ compilers
Just implement both 'GetOrLoadFromFile' functions:
#include <string>
struct R1
{
void load (const std::string &name) {}
};
struct R2
{
void load (const std::string &name0, const std::string name1) {}
};
template<typename R>
struct M
{
R *get_or_load (const std::string &name)
{
R *p = new R();
p->load (name);
return p;
}
R *get_or_load (const std::string &name0,
const std::string &name1)
{
R *p = new R();
p->load (name0, name1);
return p;
}
};
M<R1> m1;
M<R2> m2;
int
main ()
{
R1 *p0 = m1.get_or_load ("foo");
// R1 *p1 = m2.get_or_load ("foo"); // error
R2 *q0 = m2.get_or_load ("foo", "bar");
// R2 *q1 = m1.get_or_load ("foo", "bar"); // error
}
The "wrong" member function will not be instantiated, unless actually there's a call to it, in which case the compiler will exit with diagnostics.

What is the syntax for storing a specific class's member functions in a vector?

I did quite a bit of searching, but the combination of * () and class scope has greatly hindered me in understanding of the syntax, with each edit throwing a new error, any help guys?
What I'm trying to do:
Declare a std::vector of pointers to member functions found in MyClass.h
Assign the actual member functions to the std::vector in MyClass.cpp's constructor
The member functions are not static
Thanks!
I'm curious where you're going to use them from. You see in order to call a C++ class member function you need to have an instance pointer with which to call it (each member function needs a this in order to access the class state). So normally you'd wrap the member function pointer together with the instance pointer with std::bind and then maybe store the result in std::function. To put them in vector they're all going to need the same signature.
Is this the kind of thing you were looking for:
class P
{
typedef std::function<void (void)> func_t;
std::vector<func_t> functions;
public:
P()
{
functions.push_back(std::bind(&P::foo1, this));
functions.push_back(std::bind(&P::foo2, this));
functions.push_back(std::bind(&P::foo3, this));
}
void foo1(void)
{
std::cout << "foo1\n";
}
void foo2(void)
{
std::cout << "foo2\n";
}
void foo3(void)
{
std::cout << "foo3\n";
}
void call()
{
for(auto it = functions.begin(); it != functions.end(); ++it)
{
(*it)();
}
}
};
int main()
{
P p;
p.call();
}
After further clarification from the OP I'll propose this:
class P
{
typedef std::function<void (void)> func_t;
std::map<const char*, func_t> functions;
public:
P()
{
functions["foo1"] = std::bind(&P::foo1, this);
functions["foo2"] = std::bind(&P::foo2, this);
functions["foo3"] = std::bind(&P::foo3, this);
}
void foo1(void)
{
std::cout << "foo1\n";
}
void foo2(void)
{
std::cout << "foo2\n";
}
void foo3(void)
{
std::cout << "foo3\n";
}
void call_by_name(const char* func_name)
{
functions[func_name]();
}
};
int main()
{
P p;
p.call_by_name("foo1");
p.call_by_name("foo2");
p.call_by_name("foo3");
}
You can use member function pointers like this (the C++11 is unrelated to that part):
struct S {
int foo(){std::cout<<"foo"; return 0;}
int bar(){std::cout<<"bar"; return 0;}
};
int main() {
std::vector<int(S::*)()> funcs{&S::foo, &S::bar};
S s;
for (auto func : funcs) {
(s.*func)();
}
}
However, if you use C++11, std::function can make it a bit cleaner:
std::vector<std::function<int(S &)>> funcs{&S::foo, &S::bar};
S s;
for (auto func : funcs) {
func(s);
}
If you use C++03, Boost has boost::function, which is similar.