I'm attempting to replace a series of static to non static member function pairs throughout my code, I can achieve this with a macro but I was hoping I could do so with a static function which takes the non static member function as a template argument, which then gets stored as a function pointer. See the following code:
struct widget_param
{
void* ptr;
};
struct widget_data
{
bool(*callback)(widget_param*);
};
template <class CLASSNAME>
class widget_base
{
protected:
static CLASSNAME* get_instance(widget_param* param)
{
return static_cast<CLASSNAME*>(param->ptr);
}
public:
template <bool(CLASSNAME::*f)(widget_param*)>
static bool static_to_nonstatic(widget_param* param)
{
return get_instance(param)->*f(param);
}
};
class widget_derived : public widget_base<widget_derived>
{
public:
// Attempting to replace this function
static bool static_do_stuff(widget_param* param)
{
return get_instance(param)->do_stuff(param);
}
bool do_stuff(widget_param* param)
{
param;
cout << "Success!";
return true;
}
};
int main() {
widget_derived derived;
//widget_data data{ widget_derived::static_do_stuff}; // Current approach
widget_data data{ widget_derived::static_to_nonstatic<widget_derived::do_stuff> };
widget_param param{ &derived };
data.callback(¶m);
return 0;
}
I was expecting the template to evaluate to:
static bool static_to_nonstatic(widget_param* param);
Is it possible to do what I'm trying to achieve, without resorting to using a macro?
Resolved, since the call is to a member function pointer - it needed to be surrounded by parenthesis, changed the template to the following and it worked:
template <bool(CLASSNAME::*f)(widget_param*)>
static bool static_to_nonstatic(widget_param* param)
{
return (get_instance(param)->*f)(param);
}
Related
So in Java we have generics, whereby I'm looking to achieve something similar to the following in C++
public interface ListenerIF <T> {
public void onChange(T eventData);
}
...
public static void main(String[] args) {
List<ListenerIF<String>> foo = ...;
List<ListenerIF<Integer>> bar = ...;
foo.add((strUpdate) -> {/*some string operation*/});
bar.add((intUpdate) -> {/*some math*/});
foo.forEach((listener) -> listener.onChange("some change"));
bar.forEach((listener) -> listener.onChange(123));
}
But with C++ templates fundamentally being different (and needing all implementations up front), I'm trying to understand how to accomplish something similar in C++ using type erasure (and since the JVM is written in C++, I'm quite certain it's possible and just eluding me).
I can get type erasure where I want it in terms of ListenerIF, but I can't figure out how to make type T dynamic for the function ListenerIF::onChange(T). This is what I've arrived at for getting ListenerIF working (without T being dynamic, and here just as std::string):
class ListenerIF {
public:
//how do I get the parameter to this function to be dynamic?
virtual void onChange(std::string) = 0;
};
template<typename LISTENER>
class Listener: public ListenerIF {
public:
//how do I get the parameter to this function to be dynamic?
void onChange(std::string update) {
l.onChange(update);
private:
LISTENER l;
};
class Foo {
public:
//how do I get the parameter to this function to be dynamic?
void onChange(std::string);
};
class Bar {
public:
//how do I get the parameter to this function to be dynamic?
void onChange(std::string);
};
void Foo::onChange(std::string update){}
void Bar::onChange(std::string update){}
int main() {
std::vector<ListenerIF *> listeners;
listeners.push_back(new Listener<Foo>());
listeners.push_back(new Listener<Bar>());
for(std::vector<ListenerIF *>::iterator listenersItr = listeners.begin(); listenersItr < listeners.end(); listenersItr++){
(*listenersItr)->onChange("some string update");
}
Which is all fine if I just want to 'onChange' to just be for strings, but if I want to have a completely different 'onChange' type to be an int, float, or some other object type then this breaks down.
Am I just not understanding something simple that I've left out?
The parameter is not erased in the Java version (ListenerIF<T>).
The equivalent C++ would also keep the parameter:
template <typename T> // <- need a template parameter
class listener_interface {
public:
virtual void on_change(const T& data) = 0;
};
You need to apply the template to ListenerIF itself, just like the Java code does, eg:
#include <vector>
#include <memory>
template <typename T>
class ListenerIF {
public:
virtual ~ListenerIF() {};
virtual void onChange(const T &eventData) = 0;
};
template <typename T>
using listenerIF_ptr = std::unique_ptr<ListenerIF<T>>;
...
class FooListener : public ListenerIF<std::string> {
public:
void onChange(const std::string &eventData) override {
/* some string operation */
}
};
class BarListener : public ListenerIF<int> {
public:
void onChange(const int &eventData) override {
/* some math */
}
};
...
int main() {
std::vector<ListenerIF_ptr<std::string>> foo;
std::vector<ListenerIF_ptr<int>> bar;
foo.push_back(std::make_unique<FooListener>());
bar.push_back(std::make_unique<BarListener>());
for(auto &listener : foo) { listener->onChange("some change"); }
for(auto &listener : bar) { listener->onChange(123); }
}
Demo
However, in this situation, I would suggest using std::function (or even a plain function pointer) with lambdas, instead of using polymorphic interface types, eg:
#include <vector>
#include <functional>
template <typename T>
using listenerIF = std::function<void(const T&)>;
// or: listenerIF = void(*)(const T&);
int main() {
std::vector<listenerIF<std::string>> foo;
std::vector<listenerIF<int>> bar;
foo.push_back(
[](const std::string &eventData){
/* some string operation */
}
);
bar.push_back(
[](const int &eventData) {
/* some math */
}
);
for(auto &listener : foo) { listener("some change"); }
for(auto &listener : bar) { listener(123); }
}
Demo
I have a function that runs a callback:
void run_callback(void(*callback)(uint32_t)) {
callback(100);
}
This works with static functions,
void global_callback(uint32_t);
int main() {
run_callback(global_callback);
}
but not with member functions.
class A {
int x;
public:
void callback(uint32_t);
};
int main() {
A foo;
run_callback(foo.callback);
}
I work around this with a static wrapper function.
void run_member_callback(void* obj, void(*callback)(void*,uint32_t)) {
callback(obj, 100);
}
class B {
int x;
public:
static void static_callback(void* obj, uint32_t value) {
static_cast<B*>(obj)->callback(value);
}
void callback(uint32_t);
};
int main() {
B foo;
run_member_callback(&foo, foo.static_callback);
}
Is there a simple way to pass a member function as an argument?
edit:
I'm trying to avoid STL, and templates aren't an option since my implementation of run_callback is virtual.
You are doing some weird, C-ish things. Use C++ features. I personally would use a template for run_callback and a lambda for passing the member function:
template <class F>
void run_callback(F callback)
{
callback(100);
}
class A
{
int x;
public:
void callback(uint32_t);
};
int main()
{
A foo{};
run_callback([&](uint32_t a) { return foo.callback(a); });
}
If you capture the object by reference take care it outlives the run_callback call. Otherwise capture it by value.
What is a lambda expression in C++11?
I have several classes which each store and call a callback function. The callback functions' signatures have different parameter and return types, but all of them take just one parameter.
To verify that these classes call their callbacks when they should, I'm trying to write a general test class which (1) provides a callback function which takes one parameter, (2) lets the user query whether that function has been called, and (3) lets the user examine the parameter which was passed to that function. So far, I have something like this:
template<class ReturnType, class ParameterType> class Callable
{
public:
Callable() : m_called(false), m_param() {}
ReturnType operator()(ParameterType param)
{
m_called = true;
m_param = param;
return Returntype();
}
bool Called() { return m_called; }
ParameterType Param() { return m_param; }
private:
bool m_called;
ParameterType m_param;
};
Here's a class which might be tested using class Callable:
#include <boost/function.hpp>
class ToBeTested
{
ToBeTested(boost::function<bool (int)> callback) : m_callback(callback) {};
boost::function<bool (int)> m_callback;
// (methods which should cause the callback to be called here)
};
Here's some test code:
#include <boost/bind.hpp>
int main(int, char**)
{
Callable<bool, int> callable;
ToBeTested tbt(boost::bind(&Callable<bool, int>::operator());
// (tell tbt it should call its callback here)
if (callable.Called()
{
if (EXPECTED_VALUE == callable.Param();
return 0;
}
return -1;
}
This gives me (1) and (2), but there's a problem with (3) when the callback takes its parameter by reference: Callable::m_param is a reference type and therefore can't be default initialised. I could fix that by making Callable::operator() take its parameter by reference, like this:
ReturnType operator()(ParameterType & param)
...but then I can't use class Callable when the callback function takes its parameter by value.
Is there a way to make my test class work regardless of whether the callback function takes its parameter by reference, or do I need to write two nearly-identical test classes?
You could try something like this, where references are actually stored as pointers:
template<typename T>
struct ref_to_ptr
{
typedef T type;
static T wrap(T x) { return x; }
static T unwrap(T x) { return x; }
};
template<typename T>
struct ref_to_ptr<T&>
{
typedef T* type;
static T* wrap(T& x) { return &x; }
static T& unwrap(T* x) { return *x; }
};
template<class ReturnType, class ParameterType> class Callable
{
public:
Callable() : m_called(false), m_param() {}
ReturnType operator()(ParameterType param)
{
m_called = true;
m_param = ref_to_ptr<ParameterType>::wrap(param);
return Returntype();
}
bool Called() { return m_called; }
ParameterType Param() { return ref_to_ptr<ParameterType>::unwrap(m_param); }
private:
bool m_called;
typename ref_to_ptr<ParameterType>::type m_param;
};
I need to instantiate a free template function (FTF) within a template class (TC). The FTF takes as a template parameter one of the template parameters of the TC. The TC also holds generic pointers to these FTF's, and these functions are called through the pointers.
The step of taking a pointer to a FTF is not enough to instantiate it, and I receive linker errors from the GCC toolchain. MSDN illustrates FTF specification as so -- however my instantion of the FTF is dependant on a template parameter of my TC, and therefore the FTF instantiation cannot be placed in free scope.
Is this possible ? I am attaching some basic generated code, the issue is in the constructor of the class test_service, where I assign the pointer of a free function into a custom container. I get a linker error telling me the free function cannot be found (uninstantiated). I know that specifying a call to the template function in the class somewhere will produce a instantiation, however I am only going to be making a call via a pointer.
#include "rpc_common.h"
#include <boost/cstdint.hpp>
namespace rubble { namespace rpc {
struct test_service_dummy_tag{};
template<typename T>
class test_service_skel
{
public:
bool Init() {}
bool TearDown() {}
bool test_one(TestRequest,TestResponse){};
private:
};
template<typename T_IMPL>
bool test_service_test_one(T_IMPL & impl,ClientRequest & request)
{
return 0;
}
template<typename T_IMPL=test_service_skel<test_service_dummy_tag> >
class test_service
{
public:
test_service()
{
// uncomment the following two lines and a instantiation will occur.
// ClientRequest cr;
//test_service_test_one<T_IMPL>(m_impl,cr);
m_dispatch_table.SetEntry( Oid("test_one",0),(void *) & test_service_test_one<T_IMPL>);
}
bool Init() { return m_impl.Init(); };
bool TearDown() { return m_impl.TearDown(); };
private:
T_IMPL m_impl;
OidContainer<Oid,void *> m_dispatch_table;
};
} }
EDIT: self-contained minimal version
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T>
bool test_function()
{
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = (void *) & test_function<T>;
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
There is no problem iff you don't use a void*, i.e.: http://www.ideone.com/eRgUG
However, if you insist on storing the pointer in a void*, then you need to take the address using a specific function pointer first and then cast - e.g.
bool (*temp)() = &test_function<T>;
dispatch = reinterpret_cast<void*>(temp); // YUCK
This gives the compiler enough context to generate the address for you.
Ahh - just saw DeadMG's answer, the function to generate the void* is neater...
Your self-contained example wouldn't compile for me with a strange error about overloaded functions, when there is no overloading going on, with MSVC. I did, however, manage to work around it.
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T> void* to_void_pointer(T t) {
return reinterpret_cast<void*>(t);
}
template<typename T>
bool test_function()
{
return true;
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = to_void_pointer(&test_function<T>);
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
This compiles cleanly. I suspect that whatever behaviour you're seeing and I saw is a compiler error.
Suppose I have some per-class data: (AandB.h)
class A
{
public:
static Persister* getPersister();
}
class B
{
public:
static Persister* getPersister();
}
... and lots and lots more classes. And I want to do something like:
persistenceSystem::registerPersistableType( A::getPersister() );
persistenceSystem::registerPersistableType( B::getPersister() );
...
persistenceSystem::registerPersistableType( Z::getPersister() );
... for each class.
My question is: is there a way to automate building a list of per-type data so that I don't have to enumerate each type in a big chunk (as in the above example)?
For example, one way you might do this is: (AutoRegister.h)
struct AutoRegisterBase
{
virtual ~AutoRegisterBase() {}
virtual void registerPersist() = 0;
static AutoRegisterBase*& getHead()
{
static AutoRegisterBase* head= NULL;
return head;
}
AutoRegisterBase* next;
};
template <typename T>
struct AutoRegister : public AutoRegisterBase
{
AutoRegister() { next = getHead(); getHead() = this; }
virtual void registerPersist()
{
persistenceSystem::registerPersistableType( T::getPersister() );
}
};
and use this as follows: (AandB.cxx: )
static AutoRegister<A> auto_a;
static AutoRegister<B> auto_b;
Now, after my program starts, I can safely do: (main.cxx)
int main( int, char ** )
{
AutoRegisterBase* p = getHead();
while ( p )
{
p->registerPersist();
p = p->next;
}
...
}
to collect each piece of per-type data and register them all in a big list somewhere for devious later uses.
The problem with this approach is that requires me to add an AutoRegister object somewhere per type. (i.e. its not very automatic and is easy to forget to do). And what about template classes? What I'd really like is for the instantiation of a template class to somehow cause that class to get automatically registered in the list. If I could do this I would avoid having to have the user of the class (rather than the author) to remember to create a:
static AutoRegister< SomeClass<X1> > auto_X1;
static AutoRegister< SomeClass<X2> > auto_X2;
...
etc....
for each template class instantiation.
For FIW, I suspect there's no solution to this.
You can execute something before main once if a instantiation of a template is made. The trick is to put a static data member into a class template, and reference that from outside. The side effect that static data member triggers can be used to call the register function:
template<typename D>
struct automatic_register {
private:
struct exec_register {
exec_register() {
persistenceSystem::registerPersistableType(
D::getPersister()
);
}
};
// will force instantiation of definition of static member
template<exec_register&> struct ref_it { };
static exec_register register_object;
static ref_it<register_object> referrer;
};
template<typename D> typename automatic_register<D>::exec_register
automatic_register<D>::register_object;
Derive the class you want to be auto-registered from automatic_register<YourClass> . The register function will be called before main, when the declaration of referrer is instantiated (which happens when that class is derived from, which will implicitly instantiate that class from the template).
Having some test program (instead of the register function, a function do_it is called):
struct foo : automatic_register<foo> {
static void do_it() {
std::cout << " doit ";
}
};
int main() {
std::cout << " main ";
}
Yields this output (as expected):
doit main
Register each template at run-time in the constructor. Use a static variable per template to check if the type has already been registered. The following is a quickly hacked together example:
#include <iostream>
#include <vector>
using namespace std;
class Registerable {
static vector<Registerable *> registry_;
public:
static void registerFoo(Registerable *p)
{
registry_.push_back(p);
}
static void printAll()
{
for (vector<Registerable *>::iterator it = registry_.begin();
it != registry_.end(); ++it)
(*it)->print();
}
virtual void print() = 0;
};
vector<Registerable *> Registerable::registry_;
template <typename T>
class Foo : public Registerable {
static bool registered_;
public:
Foo()
{
if (!registered_) {
registerFoo(this);
registered_ = true;
}
}
void print()
{
cout << sizeof (T) << endl;
}
};
template <typename T> bool Foo<T>::registered_ = false;
int
main(int argc, char *argv[])
{
Foo<char> fooChar;
Foo<short> fooShort;
Foo<int> fooInt;
Registerable::printAll();
return 0;
}
It should output the size of each template parameter in the order the classes were instantiated:
1
2
4
This version removes the registration code from each constructor and puts it in a base class.
#include <iostream>
#include <vector>
using namespace std;
class Registerable {
static vector<Registerable *> registry_;
public:
static void registerFoo(Registerable *p)
{
registry_.push_back(p);
}
static void printAll()
{
for (vector<Registerable *>::iterator it = registry_.begin();
it != registry_.end(); ++it)
(*it)->print();
}
virtual void print() = 0;
};
vector<Registerable *> Registerable::registry_;
template <typename T>
class Registerer : public Registerable {
static bool registered_;
public:
Registerer(T *self)
{
if (!registered_) {
registerFoo(self);
registered_ = true;
}
}
};
template <typename T> bool Registerer<T>::registered_ = false;
template <typename T>
class Foo : public Registerer<Foo<T> > {
public:
Foo() : Registerer<Foo<T> >(this) { }
void print()
{
cout << sizeof (T) << endl;
}
};
int
main(int argc, char *argv[])
{
Foo<char> fooChar;
Foo<short> fooShort;
Foo<int> fooInt;
Registerable::printAll();
return 0;
}
I added an example of another non-template class using the registry. So, the final output would be:
foo: 1
foo: 2
foo: 4
bar
The Registerable solution is a neat idea, but has a couple of issues.
Ideally, I'd like to not add code to the constructor:
Because it relies on calling the constructor in order to register the type, it's a
little haphazard about what gets registered and what doesn't.
For things like persistence, I may never call the constructor of a particular type
before using the list, but I may need the type's data in the list in order to
know how to un-persist an object in a file.
There's runtime cost during the constructor call. I'd like to front load the time cost
and not pay the cost many times. If I had a vector of these objects and resized the
vector I'd pay the time-cost each time the copy constructor was called.
Use file-level static blocks to perform the different registrations
A static block? What's that?
A static block is a block of code (i.e. code between curly braces, which defines a scope) that gets executed sometime before main() runs. Java has this feature, and C++ has it too-
Whatch'a talkin' bout, Willis? C++ don't have no static blocks!
No, really, C++ has static blocks. You just need to, uh, shall we say, "expose" their existence.
Hmm. Curious. And how do the static blocks help my registration problem?
It's really very simple. Right after you define class A, you register it like so:
class A { /* ... whatever ... */ };
static_block {
persistenceSystem::registerPersistableType(A::getPersister());
}
There is one caveat, though: static blocks can be a part of the static initialization order fiasco together with any statically-initialized part of your persistence system; so you need to make sure it's ok for these static blocks to run before (most) other statics; and that it's ok for the different classes' Persister's to be registered in arbitrary order.