Why would I want a .* operator in C++? - c++

I recently found out that the .* operator (and the closely related ->* operator) exists in C++. (See this question.)
Seems neat at first, but why would I ever need such a thing? The two answers in the linked question provided contrived examples which would benefit from a direct function call.
Where a direct function call is inconvenient, a function object could be used instead, like the lambda functions that may be used in std::sort. This removes a level of indirection and hence would be more performant than using .*.
The linked question also mentioned a simplified version of this example:
struct A {
int a;
int b;
};
void set_member(A& obj, int A::* ptr, int val){
obj.*ptr = val;
}
int main()
{
A obj;
set_member(obj, &A::b, 5);
set_member(obj, &A::a, 7);
// Both members of obj are now assigned
}
But it's pretty trivial (perhaps even better practice because it's cleaner and isn't unnecessarily constrained to members of A) to do this instead:
struct A {
int a;
int b;
};
void set_me(int& out, int val){
out = val;
}
int main()
{
A obj;
set_me(obj.b, 5);
set_me(obj.a, 7);
// Both members of obj are now assigned
}
In conclusion, a pointer-to-member-function might be replaced by a function object, and a pointer-to-member-variable might be replaced by a direct reference of said variable or a function object. Doing so might also increase the efficiency of the code due to one less indirection.
This question only provides examples where my conclusion stands, so it does not answer my question.
Apart from interfacing legacy code which uses .* (in which there would be no choice at all), when, really, would I want to use .*?

Your example is too trivial to be illustrative. Consider a bit more complicated one
struct A {
int a;
int b;
};
void set_n_members(A objs[], unsigned n, int A::* ptr, int val)
{
for (unsigned i = 0; i < n; ++i)
objs[i].*ptr = val;
}
int main()
{
A objs[100];
set_n_members(objs, 100, &A::b, 5);
set_n_members(objs, 100, &A::a, 7);
}
How would you rewrite this without int A::* ptr and without inducing code bloat?

You could create collections of pointers to members and iterate over them. E.g.:
struct UserStrings
{
std::string first_name;
std::string surname;
std::string preferred_name;
std::string address;
};
...
std::array<std::string UserStrings::*, 4> str_cols = { &UserStrings::first_name, &UserStrings::surname, &UserStrings::preferred_name, &UserStrings::address };
std::vector<UserStrings> users = GetUserStrings();
for (auto& user : users)
{
for (auto& column : str_cols)
{
SanitizeForSQLQuery(user.*column);
}
}

It is used to implement std::mem_fn, which is used to implement std::function.
The following code shows how the ->* operator works in a naive Function class implemention.
Similarly, you can implement a member invoker class using the .* operator and a class reference.
#include <iostream>
class A
{
public:
void greet()
{
std::cout << "Hello world"<<std::endl;
}
};
template<typename R, typename ...TArgs>
class Invoker
{
public:
virtual R apply(TArgs&& ...args) = 0;
};
template<typename C, typename R, typename ...TArgs>
class MemberInvoker :public Invoker<R, TArgs...>
{
protected:
C* sender;
R(C::*function)(TArgs ...args);
public:
MemberInvoker(C* _sender, R(C::*_function)(TArgs ...args))
:sender(_sender)
, function(_function)
{
}
virtual R apply(TArgs&& ...args) override
{
return (sender->*function)(std::forward<TArgs>(args)...);
}
};
template<typename T>
class Func
{
};
template<typename R, typename ...TArgs>
class Func<R(TArgs...)>
{
public:
Invoker<R,TArgs...>* invoker=nullptr;
template<typename C>
Func(C* sender, R(C::*function)(TArgs...))
{
invoker =new MemberInvoker<C, R, TArgs...>(sender, function);
}
R operator()(TArgs&& ...args)
{
return invoker->apply(std::forward<TArgs>(args)...);
}
~Func()
{
if (invoker)
{
delete invoker;
invoker = nullptr;
}
}
};
int main()
{
A a;
Func<void()> greetFunc(&a, &A::greet);
greetFunc();
system("PAUSE");
}

Let's say you wanted to write a LINQ style library for C++ that could be used something like this:
struct Person
{
std::string first_name;
std::string last_name;
std::string occupation;
int age;
int children;
};
std::vector<Person> people = loadPeople();
std::vector<std::string> result = from(people)
.where(&Person::last_name == "Smith")
.where(&Person::age > 30)
.select("%s %s",&Person::first_name,&Person::last_name);
for(std::string person : result) { ... };
Under the covers, the where function accepts an expression tree containing a pointer to member (among other stuff) and is applied to each vector item looking for one that matches. The select statement accepts a format string and some pointer to members and does an sprintf style formatting of whichever vector items get through the where statements.
I have written something like this, and there are several others out there that do it slightly differently (Is there a LINQ library for C++?). Pointer-to-member allows the library user to specify whichever members of their struct that they want and the library doesn't need to know anything about what they might do.

Related

C++20 best way to convert abstract class (interface) and mixins into concept

I used to define my template requirement through abstract class, e.g.
#include <iostream>
#include <random>
/// Generic interface
template<typename A, typename B>
struct Interface {
virtual A callback_A(const std::vector<A>& va) = 0;
virtual const B& callback_B() = 0;
};
/// Mixin style, used to "compose" using inheritance at one level, no virtual
struct PRNG_mt64 {
std::mt19937_64 prng;
explicit PRNG_mt64(size_t seed) : prng(seed) {};
};
/// Our implementation
template<typename A>
struct Implem :
public Interface<A, std::string>,
public PRNG_mt64 {
std::string my_string{"world"};
explicit Implem(size_t seed) : PRNG_mt64(seed) {}
A callback_A(const std::vector<A>& a) override { return a.front(); }
const std::string& callback_B() override { return my_string; }
};
/// Function using our type. Verification of the interface is perform "inside" the function
template<typename T>
void use_type(T& t) {
auto& strings = static_cast<Interface<std::string, std::string>&>(t);
std::cout << strings.callback_A({"hello"}) << " " << strings.callback_B() << std::endl;
auto& prng = static_cast<PRNG_mt64&>(t).prng;
std::uniform_real_distribution<double> dis(0.0, 1.0);
std::cout << dis(prng) << std::endl;
}
int main(int argc, char **argv) {
size_t seed = std::random_device()();
Implem<std::string> my_impl(seed);
use_type(my_impl);
}
One benefit of using the asbtract class is the clear specification of the interface, easily readable. Also, Implem has to confom to it (we cannot forget the pure virtual).
A problem is that the interface requirement is hidden in the static cast (that comes from my real use case where a composite "state" is used by several polymorphic components - each component can cast the state to only see what it needs to see). This is "solved" by concepts (see below).
Another one is that we are using the virtual mechanism when we have no dynamic polymorphism at all, so I would like to get rid of them. What is the best way to convert this "interface" into concept?
I came up with this:
#include <iostream>
#include <random>
/// Concept "Interface" instead of abstract class
template<typename I, typename A, typename B>
concept Interface = requires(I& impl){
requires requires(const std::vector<A>& va){{ impl.callback_A(va) }->std::same_as<A>; };
{ impl.callback_B() } -> std::same_as<const B&>;
};
/// Mixin style, used to "compose" using inheritance at one level, no virtual
struct PRNG_mt64 {
std::mt19937_64 prng;
explicit PRNG_mt64(size_t seed) : prng(seed) {};
};
/// Our implementation
template<typename A>
struct Implem : public PRNG_mt64 {
std::string my_string{"world"};
/// HERE: requires in the constructor to "force" interface. Can we do better?
explicit Implem(size_t seed) requires(Interface<Implem<A>, A, std::string>): PRNG_mt64(seed) {}
A callback_A(const std::vector<A>& a) { return a.front(); }
const std::string& callback_B() { return my_string; }
};
/// Function using our type. Verification of the interface is now "public"
template<Interface<std::string, std::string> T>
void use_type(T& t) {
std::cout << t.callback_A({"hello"}) << " " << t.callback_B() << std::endl;
auto& prng = static_cast<PRNG_mt64&>(t).prng;
std::uniform_real_distribution<double> dis(0.0, 1.0);
std::cout << dis(prng) << std::endl;
}
int main(int argc, char **argv) {
size_t seed = std::random_device()();
Implem<std::string> my_impl(seed);
use_type(my_impl);
}
Questions:
Is that actually the thing to do in the first place? I saw several posts on the internet explaning concepts, but they are always so shallow that I'm afraid I'll miss something regarding perfect forwarding, move, etc...
I used a requires requires clause to keep function arguments close to their usage (useful when having many methods). However, the "interface" information is now hard to read: can we do better?
Also, the fact that Implem implements the interface is now the part that is "hidden" inside the class. Can we make that more "public" without having to write another class with CRTP, or limiting the boilerplate code as much as possible?
Can we do better for the "mixin" part PRNG_mt64? Ideally, turning this into a concept?
Thank you!
Your pre-C++20 approach is pretty bad, but at least it sounds like you understand the problems with it. Namely, you're paying 8 bytes for a vptr when you don't need it; and then strings.callback_B() is paying the cost of a virtual call even though you could be calling t.callback_B() directly.
Finally (this is relevant, I promise), by funneling everything through the base-class reference strings, you're taking away Implem's ability to craft a helpful overload set. I'll show you a simpler example:
struct Interface {
virtual int lengthOf(const std::string&) = 0;
};
struct Impl : Interface {
int lengthOf(const std::string& s) override { return s.size(); }
int lengthOf(const char *p) { return strlen(p); }
};
template<class T>
void example(T& t) {
Interface& interface = t;
static_assert(!std::same_as<decltype(interface), decltype(t)>); // Interface& versus Impl&
int x = interface.lengthOf("hello world"); // wastes time constructing a std::string
int y = t.lengthOf("hello world"); // does not construct a std::string
}
int main() { Impl impl; example(impl); }
The generic-programming approach would look like this, in C++20:
template<class T>
concept Interface = requires (T& t, const std::string& s) {
{ t.lengthOf(s) } -> convertible_to<int>;
};
struct Impl {
int lengthOf(const std::string& s) override { return s.size(); }
int lengthOf(const char *p) { return strlen(p); }
};
static_assert(Interface<Impl>); // sanity check
template<Interface T>
void example(T& t) {
Interface auto& interface = t;
static_assert(std::same_as<decltype(interface), decltype(t)>); // now both variables are Impl&
int x = interface.lengthOf("hello world"); // does not construct a std::string
int y = t.lengthOf("hello world"); // does not construct a std::string
}
int main() { Impl impl; example(impl); }
Notice that there is no way at all to get back the "funneling" effect you had with the base-class approach. Now there is no base class, the interface variable itself is still statically a reference to an Impl, and calling lengthOf will always consider the full overload set provided by the Impl. This is a good thing for performance — I think it's a good thing in general — but it is radically different from your old approach, so, be careful!
For your callback_A/B example specifically, your concept would look like
template<class T, class A, class B>
concept Interface = requires (T& impl, const std::vector<A>& va) {
{ impl.callback_A(va) } -> std::same_as<A>;
{ impl.callback_B() } -> std::same_as<const B&>;
};
In real life I would very strongly recommend changing those same_ases to convertible_tos instead. But this code is already very contrived, so let's not worry about that.
In C++17 and earlier, the equivalent "concept" (type-trait) definition would look like this (complete working example in Godbolt). Here I've used a macro DV to shorten the boilerplate; I wouldn't actually do that in real life.
#define DV(Type) std::declval<Type>()
template<class T, class A, class B, class>
struct is_Interface : std::false_type {};
template<class T, class A, class B>
struct is_Interface<T, A, B, std::enable_if_t<
std::is_same_v<int, decltype( DV(T&).callback_A(DV(const std::vector<A>&)) )> &&
std::is_same_v<int, decltype( DV(T&).callback_B() )>
>> : std::true_type {};

How to specify the same templated member function for multiple class types in c++?

In an effort to avoid a lot of typing, I would like to define a function once for multiple classes. My hope is that the template system would provide the definition to each of them. I suppose a non-trivial macro could accomplish this also, but they seems to be much less preferred. I do not wish to use inheritance where I could create a base class for S1,S2, due to its complications.
struct S1 {
bool print(int i);
};
struct S2 {
bool print(int i);
};
// bool S1::print(int i) { i=+1; std::cout<<i; return true; } NOTE: this is the line I don't want to type many times for each S*
template< typename T >
bool T::print(int i) { i=+1; std::cout<<i; return true; } // TODO
int main() {
S1 s1 {};
s1.print( 5 );
}
You can't use a template to "inject" a free function to become a member function of each of a number of independent classes. Sorry, just not how things work.
If you wanted to badly enough, you could do this with inheritance:
#include <iostream>
struct Base {
public:
bool print() {
std::cout << "Printing something\n";
return true;
}
};
struct S1 : Base { };
struct S2 : Base { };
int main() {
S1 s1;
s1.print();
S2 s2;
s2.print();
}
But note: inheritance brings a whole host of issues of its own, so it's open to question whether you actually want to do this or not.
What about something like this?
struct function
{
bool print(int i);
}
struct s1: public function
{
}
Now you will be able to use the print function from s1.

C++ compile time template polymorphism

I would like to create an application in which I can define list of typed questions, then iterate over this list and ask user to enter answers, storing them in another list, then go over answers, validate them and provide a result.
My current naive approach is something like this:
class Question {
std::string message;
public:
Question(const std::string& msg) : message{msg} {}
std::string& getQuestion(void) const {
return this->message;
}
virtual ~Question(void) = 0;
};
Question::~Question(void) {}
template<class AnswerType>
class Prompt : public Question {
Prompt(std::string& msg) : Question{msg} {}
virtual ~Prompt(void) {}
};
class Answer<class T> {
T answ;
public:
Answer(const T& answer) : answ{answer} {}
T getAnswer(void) const {
return this->answ;
}
};
and I would like to do something like:
std::list< const Question* > whatToAsk{
new Prompt<int>{"Your age"},
new Prompt<std::string>{"Your name"},
new Prompt<float>{"Your weight"}
};
for(auto q in whatToAsk) {
Answer< "derived q template parameter" > a{};
std::cout << q->getQuestion() << ": ";
std::cin >> a;
// ... to be continued ...
}
storing questions (Prompt< T >) inside of std::list< const Question* >.
But problematic part for me is that I've to use downcasting (with runtime checking), virtual functions (runtime polymorphism) or double dispatch (again with runtime overhead).
My concern is that types are known during compilation, because list of questions will be hardcoded in the source code and I want to avoid runtime overhead and achieve compile-time static polymorphism.
How can I achieve this? Some kind of traits maybe?
If you don't want to use virtual functions/dynamic_casts you should
Make each question of a different type.
Store them in a tuple, not in a list.
Iterate using a special function (forEachArgument -- it's googleable).
It is much simpler to do it with virtual functions and unless you wil have thousands of questions the runtime overhead is negligible.
I'm not an expert but maybe you can use c++11 variadic templates that would allow you to have an array of different types, and thus would not cause any overhead due to downcast.
this link may interest you Create static array with variadic templates
A few sparse notes, more than a reply
Add the answer handling stuff section a member function of question. This way you can know the type of question. Something like
void ask()
{
Answer<T> answer ;
std::cint >> a ;
....
}
Use std::shared_ptr instead of plain pointers.
Probably an idiom known as virtual constructor as question factory can be helpful for question building
Something like
Question *make_question(int type)
{
switch (type)
{
case 0: return new Prompt<int>() ;
case 1: return new Prompt<std::string>() ;
...
}
}
If you are using c++14 you could do something like:
#include <iostream>
template <class FirstQuestion, class... OtherQuestions>
struct QuestionList {
template <class Functor>
void foreach(Functor &&functor) {
functor(FirstQuestion());
QuestionList<OtherQuestions...> oql;
oql.foreach(functor);
}
};
template <class FirstQuestion>
struct QuestionList<FirstQuestion> {
template <class Functor>
void foreach(Functor &&functor) {
functor(FirstQuestion());
}
};
template <class AnswerType, const char *QuestionString>
struct Question {
static AnswerType answer;
static void print_question() {
std::cout << QuestionString << std::endl;
}
static void get_answer() {
std::cin >> answer;
}
};
template <class AnswerType, const char *QuestionString>
AnswerType Question<AnswerType, QuestionString>::answer;
constexpr char questionstrings1[] = "lorem";
constexpr char questionstrings2[] = "ipsum";
int main() {
QuestionList<Question<int, questionstrings1>, Question<float, questionstrings2> > a;
a.foreach([](auto x){ x.print_question(); x.get_answer(); });
}
To access the answer in a loop you can simply:
a.foreach([](auto x){ /*doing something with x.answer*/ };
PS have in mind that prompting user for an answer kills potential efficiency of the non-runtime polymorhism...

C++ Push Multiple Types onto Vector

Note: I know similar questions to this have been asked on SO before, but I did not find them helpful or very clear.
Second note: For the scope of this project/assignment, I'm trying to avoid third party libraries, such as Boost.
I am trying to see if there is a way I can have a single vector hold multiple types, in each of its indices. For example, say I have the following code sample:
vector<something magical to hold various types> vec;
int x = 3;
string hi = "Hello World";
MyStruct s = {3, "Hi", 4.01};
vec.push_back(x);
vec.push_back(hi);
vec.push_back(s);
I've heard vector<void*> could work, but then it gets tricky with memory allocation and then there is always the possibility that certain portions in nearby memory could be unintentionally overridden if a value inserted into a certain index is larger than expected.
In my actual application, I know what possible types may be inserted into a vector, but these types do not all derive from the same super class, and there is no guarantee that all of these types will be pushed onto the vector or in what order.
Is there a way that I can safely accomplish the objective I demonstrated in my code sample?
Thank you for your time.
The objects hold by the std::vector<T> need to be of a homogenous type. If you need to put objects of different type into one vector you need somehow erase their type and make them all look similar. You could use the moral equivalent of boost::any or boost::variant<...>. The idea of boost::any is to encapsulate a type hierarchy, storing a pointer to the base but pointing to a templatized derived. A very rough and incomplete outline looks something like this:
#include <algorithm>
#include <iostream>
class any
{
private:
struct base {
virtual ~base() {}
virtual base* clone() const = 0;
};
template <typename T>
struct data: base {
data(T const& value): value_(value) {}
base* clone() const { return new data<T>(*this); }
T value_;
};
base* ptr_;
public:
template <typename T> any(T const& value): ptr_(new data<T>(value)) {}
any(any const& other): ptr_(other.ptr_->clone()) {}
any& operator= (any const& other) {
any(other).swap(*this);
return *this;
}
~any() { delete this->ptr_; }
void swap(any& other) { std::swap(this->ptr_, other.ptr_); }
template <typename T>
T& get() {
return dynamic_cast<data<T>&>(*this->ptr_).value_;
}
};
int main()
{
any a0(17);
any a1(3.14);
try { a0.get<double>(); } catch (...) {}
a0 = a1;
std::cout << a0.get<double>() << "\n";
}
As suggested you can use various forms of unions, variants, etc. Depending on what you want to do with your stored objects, external polymorphism could do exactly what you want, if you can define all necessary operations in a base class interface.
Here's an example if all we want to do is print the objects to the console:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class any_type
{
public:
virtual ~any_type() {}
virtual void print() = 0;
};
template <class T>
class concrete_type : public any_type
{
public:
concrete_type(const T& value) : value_(value)
{}
virtual void print()
{
std::cout << value_ << '\n';
}
private:
T value_;
};
int main()
{
std::vector<std::unique_ptr<any_type>> v(2);
v[0].reset(new concrete_type<int>(99));
v[1].reset(new concrete_type<std::string>("Bottles of Beer"));
for(size_t x = 0; x < 2; ++x)
{
v[x]->print();
}
return 0;
}
In order to do that, you'll definitely need a wrapper class to somehow conceal the type information of your objects from the vector.
It's probably also good to have this class throw an exception when you try to get Type-A back when you have previously stored a Type-B into it.
Here is part of the Holder class from one of my projects. You can probably start from here.
Note: due to the use of unrestricted unions, this only works in C++11. More information about this can be found here: What are Unrestricted Unions proposed in C++11?
class Holder {
public:
enum Type {
BOOL,
INT,
STRING,
// Other types you want to store into vector.
};
template<typename T>
Holder (Type type, T val);
~Holder () {
// You want to properly destroy
// union members below that have non-trivial constructors
}
operator bool () const {
if (type_ != BOOL) {
throw SomeException();
}
return impl_.bool_;
}
// Do the same for other operators
// Or maybe use templates?
private:
union Impl {
bool bool_;
int int_;
string string_;
Impl() { new(&string_) string; }
} impl_;
Type type_;
// Other stuff.
};

null pointer when getting function pointer using boost::function::target

After reading this answer I thought I had a solution. At least the answer there is what I would like to do but I'm having a problem with the implementation.
here is an outline of what I am trying to do
typedef map<string, double*> myMap;
typedef int (*ftwpt)(const char*, const struct stat*, int);
typedef boost::function<int(const char*, const struct stat*, int)> MyFTWFunction;
int myFunction(const char*, const struct stat*, int, myMap*);
int main()
{
myMap m_map;
char tmpdir[] = "/tmp/mytmp";
MyFTWFunction f = boost::bind(myFunction,_1,_2,_3, &m_map);
ftwpt* fpt = f.target<ftwpt>();
if (fpt)
status = ftw(tmpdir, *fpt, 50);
else
{
cout << "Boost could not perform runtime conversion on function pointer" << endl;
return (EXIT_FAILURE);
}
}
the program compiles with no errors or warnings but I am getting a null pointer (fpt) returned from f.target(); at runtime. From references linked on the above stackoverflow question it seems a null pointer is returned if boost is unable to perform the runtime conversion. But I have no idea why Boost might not be able to perform the runtime conversion. Any ideas?
For that to work, you would need to know the exact type of the bind expression that you store into the boost::function object. The object boost::bind(....) returns is some weird expression template, not a function pointer.
To understand why this is needed, consider how boost::function is implemented in principle
struct base { virtual ~base() { } };
template<typename T>
struct derived : base {
derived(T t):t(t) { }
T t;
};
struct function {
template<typename T>
function(T t) {
base *b = new derived<T>(t);
}
template<typename T>
T *target() {
if(typeid(*b) == typeid(derived<T>))
return &static_cast< derived<T>* >(b)->t;
return 0;
}
base *b;
};
That's the most fundamental structure, without the operator() bloat - much like boost::any. The mechanism is called type-erasure: The constructor accepts objects of arbitrary types, and then stores an object encapsulated into an object that you may reach through virtual function calls (boost::function is optimized like hell, using its own vtable and stack-allocation to avoid new for small types and so on).
For function pointers, this works great, because you know the type of the function that you assign to the boost::function object. But for complex callable objects, it doesn't quite work anymore.
To be able to see it working and to see that it's not just working with function pointers, but also with bind expressions, consider the following code
template<typename T>
struct id { typedef T type; };
template<typename T>
id<T> make_id(T) { return id<T>(); }
struct any_type {
template<typename T>
operator id<T>() const { return id<T>(); }
};
template<typename T, typename Fn>
T *get_target(boost::function<Fn> &f, id<T>)
{ return f.template target<T>(); }
void f(int a, int b) { std::cout << a << " " << b << std::endl; }
int main() {
boost::function<void(int)> g = boost::bind(&f, _1, 10);
(*get_target(g, true ? any_type() : make_id(boost::bind(&f, _1, 10))))(2);
}
Within get_target you know the type of what boost::bind returns. You can use that to call the target call and return the object that's wrapped inside the boost::function. Within main we then call the bind expression. Please read Eric Niebler's article Conditional Love to see how this code snippet works.
The other answer points out why your code doesn't work. Here is a really ugly solution that sort of does, kind of, for certain limited situations.
typedef int (*ftwpt)(const char*, const struct stat*, int);
typedef boost::function<int(const char*, const struct stat*, int)> MyFTWFunction;
template <MyFTWFunction *callback>
class callback_binder {
public:
static int callbackThunk(const char *s, const struct stat *st, int i) {
return (*callback)(s, i);
}
};
extern void register_callback(callback_t f);
int random_func(const char *s, const struct stat *st, int i)
{
if (s && *s) {
return i;
} else {
return -1;
}
}
MyFTWFunction myfunc;
int main(int argc, const char *argv[])
{
myfunc = random_func;
register_callback(&callback_binder<&myfunc>::callbackThunk);
return 0;
}
The rules for using pointers as template arguments require that the pointer passed in as an argument be a pointer to a global variable. That global variable can, of course, be declared in an anonymous namespace.
It's ugly, and if you wanted to have several possible instances of myMap possible called back with at the same time you'd need as many global MyFTWFunction variables as possible simultaneous instances of myMap. Mostly this automates the creation of a thunk function that uses the content of a global variable to fill in the missing parameter.
Here is a version that is a LOT less flexible that does approximately the same thing for this narrow case that may make it more obvious what's going on here:
#include <map>
#include <string>
using ::std::map;
using ::std::string;
typedef map<string, double*> myMap;
typedef int (*callback_t)(const char *, struct stat *st, int);
int myFunction(const char*, struct stat *st, int, myMap*);
template <myMap **map_ptr>
class myMap_binder {
public:
static int call_my_function(const char *s, struct stat *st, int i) {
return myFunction(s, st, i, *map_ptr);
}
};
extern void register_callback(callback_t f);
myMap *mainmap;
myMap *othermap;
int main(int argc, const char *argv[])
{
myMap m_map;
myMap m_map2;
mainmap = &m_map;
othermap = &m_map2;
register_callback(&myMap_binder<&mainmap>::call_my_function);
register_callback(&myMap_binder<&othermap>::call_my_function);
return 0;
}
As you can see myMap_binder is a template that auto-generates thunk functions that stuff in the contents of a global variable into a call to your callback function.
This is a few years late, but maybe it'll help you in the future. My problem was slightly different, but you can still get the answer you want from the solution; read here:
> Messaging system: Callbacks can be anything