functors + member pointers to create signal object - c++

I have this code:
// signal supporter parent
class signalable {};
template <class typeT = signalable>
typedef void (typeT::*trig)(std::string);
template <class typeT = signalable>
class trigger
{
private:
typeT* instance;
typeT::trig fun;
public:
trigger(typeT* inst, typeT::trig function)
: instance(inst), fun(function)
{}
void operator ()(std::string param)
{
(instance->*fun)(param);
}
};
And I get lots of compile error that I bet pros know of. I'm just confused a little bit about this context.
What I want to do is clear: Pass pointer to an object, and pointer to one of it's member functions, to make a functor and pass it over in my program.
Would appreciate your helps and "corrections".
Thank you!

Are you trying to do something like this?
#include <string>
#include <iostream>
// signal supporter parent
class signalable
{
public:
void foo(std::string s) { std::cout << "hello: " << s << std::endl; }
};
template <class typeT = signalable>
class trigger
{
typedef void (typeT::*trig)(std::string);
private:
typeT* instance;
trig fun;
public:
trigger(typeT* inst, trig function)
: instance(inst), fun(function)
{}
void operator ()(std::string param)
{
(instance->*fun)(param);
}
};
int main()
{
signalable s;
trigger<> t(&s, &signalable::foo);
t("world");
}
As for some of the more specific errors in your code, most of them seem to relate to your typedef. C++11 allows "template typedefs", but they don't look like that. Have a look at this thread for an example of template typedefs:
C++ template typedef

Related

Default argument with template in C++

I'm designing an interface, by which users can define a class that tells what they want to do.
The code is something like the following,
#include <stdio.h>
class Dummy{
public:
void do(){ printf("do nothing\n"); }
};
class Task{
public:
void do(){ printf("do something\n"); }
};
template <class TASK>
void func(TASK &task = Dummy()){
task.do();
}
int main(){
func(); // do nothing
Task task;
func(task); // do something
}
How to make it work?
The main issue is this func argument:
TASK &task = Dummy()
It will not work unless it is const. This happens because non-const lvalue reference to type cannot bind to a temporary.
But if you can use const there, you can easily solve your problem:
class Dummy{
public:
void doit() const { printf("do nothing\n"); }
};
class Task{
public:
void doit() const { printf("do something\n"); }
};
template <class TASK = Dummy>
void func(const TASK &task = TASK()){
task.doit();
}
int main(){
func(); // do nothing
Task task;
func(task); // do something
}
For starters, don't have an identifier (function named) named do, since do is a language keyword. Using it as an identifier is a diagnosable error. There's no option other than changing the name of the function.
Second, the argument will of func() will need to be const, since the default value being passed is a temporary (which can only be bound to a const reference). This also means your function in the classes needs to be const qualified.
Third, when calling func() it is necessary to either pass SOME information so the compiler can work out how to instantiate the template. If you want to pass no information at all at the call site (i.e. func()) then you need to have a non-templated overload.
Fourth, use C++ streams rather than C I/O.
class Dummy
{
public:
void do_it() const { std::cout << "do nothing\n"; }
};
class Task
{
public:
void do_it() const { std::cout << "do something\n"; }
};
template <class TASK>
void func(const TASK &task)
{
task.do_it();
}
void func()
{
func(Dummy());
}
int main()
{
func(); // do nothing
Task task;
func(task); // do something
}
Option 2 is to replace the two versions of func() above with
template <class TASK = Dummy>
void func(const TASK &task = TASK())
{
task.do_it();
}

C++ Type Erasure for function parameters

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

Template type deduction with a non-copyable class

Suppose I have an autolocker class which looks something like this:
template <T>
class autolocker {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
~autolocker() {
lock->unlock();
}
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
T *lock;
};
Obviously the goal is to be able to use this autolocker with anything that has a lock/unlock method without resorting to virtual functions.
Currently, it's simple enough to use like this:
autolocker<some_lock_t> lock(&my_lock); // my_lock is of type "some_lock_t"
but it is illegal to do:
autolocker lock(&my_lock); // this would be ideal
Is there anyway to get template type deduction to play nice with this (keep in my autolocker is non-copyable). Or is it just easiest to just specify the type?
Yes you can use the scope-guard technique
struct autolocker_base {
autolocker_base() { }
protected:
// ensure users can't copy-as it
autolocker_base(autolocker_base const&)
{ }
autolocker_base &operator=(autolocker_base const&)
{ return *this; }
};
template <T>
class autolocker : public autolocker_base {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
autolocker(const autolocker& o)
:autolocker_base(o), lock(o.lock)
{ o.lock = 0; }
~autolocker() {
if(lock)
lock->unlock();
}
private:
autolocker& operator=(const autolocker&);
private:
mutable T *lock;
};
Then write a function creating the autolocker
template<typename T>
autolocker<T> makelocker(T *l) {
return autolocker<T>(l);
}
typedef autolocker_base const& autolocker_t;
You can then write it like this:
autolocker_t lock = makelocker(&my_lock);
Once the const reference goes out of scope, the destructor is called. It doesn't need to be virtual. At least GCC optimizes this quite well.
Sadly, this means you have to make your locker-object copyable since you need to return it from the maker function. But the old object won't try to unlock twice, because its pointer is set to 0 when it's copied, so it's safe.
Obviously you can't get away with autolocker being a template, because you want to use it as a type, and templates must be instantiated in order to obtain types.
But type-erasure might be used to do what you want. You turn the class template into a class and its constructor into a member template. But then you'd have to dynamically allocate an inner implementation object.
Better, store a pointer to a function that performs the unlock and let that function be an instance of a template chosen by the templatized constructor. Something along these lines:
// Comeau compiles this, but I haven't tested it.
class autolocker {
public:
template< typename T >
autolocker(T *l) : lock_(l), unlock_(&unlock<T>) { l->lock(); }
~autolocker() { unlock_(lock_); }
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
typedef void (*unlocker_func_)(void*);
void *lock_;
unlocker_func_ unlock_;
template <typename T>
static void unlock(void* lock) { ((T*)lock)->unlock(); }
};
I haven't actually tried this and the syntax might be wrong (I'm not sure how to take the address of a specific function template instance), but I think this should be doable in principle. Maybe someone comes along and fixes what I got wrong.
I like this a lot more than the scope guard, which, for some reason, I never really liked at all.
I think jwismar is correct and what you want is not possible with C++. However, a similar (not direct analogue) construct is possible with C++0x, using several new features (rvalues/moving and auto variable type):
#include <iostream>
template <typename T>
class autolocker_impl
{
public:
autolocker_impl(T *l) : lock(l) {
lock->lock();
}
autolocker_impl (autolocker_impl&& that)
: lock (that.lock)
{
that.lock = 0;
}
~autolocker_impl() {
if (lock)
lock->unlock();
}
private:
autolocker_impl(const autolocker_impl&);
autolocker_impl& operator=(const autolocker_impl&);
private:
T *lock;
};
template <typename T>
autolocker_impl <T>
autolocker (T* lock)
{
return autolocker_impl <T> (lock);
}
struct lock_type
{
void lock ()
{ std::cout << "locked\n"; }
void unlock ()
{ std::cout << "unlocked\n"; }
};
int
main ()
{
lock_type l;
auto x = autolocker (&l);
}
autolocker is a class template, not a class. Your "this would be ideal" is showing something that doesn't make sense in C++.

pointers as template parameters?

I have a container class, we'll call it
template <class T> CVector { ... }
I want to do something different with this class when T is a pointer type, e.g. something along the lines of:
template <class T*> CVector< SomeWrapperClass<T> >;
where SomeWrapperClass is expecting the type of the pointed to thing as its parameter. Unfortunately, this syntax doesn't quite work and with some digging, I haven't found a good way to get something like this working.
Why do it this way? I want to change, in a very large app, how some of our containers work when the type they're specialized on is a pointer vs. not a pointer - and ideally, i'd like to do it without changing the ~1,000 places in the code where there are things like CVector<Object*> vs CVector<int> or some such - and playing games with partial specializations seemed to be the way to go.
Am I on crack here?
If I understand you correctly, this might do what you want:
template<typename T>
class CVector { ... };
template<typename T>
class CVector<T*> : public CVector< SomeWrapperClass<T> > {
public:
// for all constructors:
CVector(...) : CVector< SomeWrapperClass<T> >(...) {
}
};
It adds an additional layer of inheritance to trick CVector<T*> into being a CVector< SomeWrapperClass<T> >. This might also be useful in case you need to add additional methods to ensure full compatibility between the expected interface for T* and the provided interface for SomeWrapperClass<T>.
This works just fine in C++...
#include <iostream>
template <class T>
class CVector
{
public:
void test() { std::cout << "Not wrapped!\n"; }
};
template <class T>
class CVector<T*>
{
public:
void test() { std::cout << "Wrapped!\n"; }
};
int main()
{
CVector<int> i;
CVector<double> d;
CVector<int*> pi;
CVector<double*> pd;
i.test();
d.test();
pi.test();
pd.test();
}
I don't think you can specialize a class using the syntax you describe... I don't know how that could possibly work. What you can do is specialize the class for pointers and re-implement its guts using the wrapper class around the raw pointers. I'm not sure if it will help, but this article describes specializing templates for pointers.
The Boost type traits library can help you achieve this. Check out the is_pointer type trait.
#include <boost/type_traits.hpp>
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class CVector {
public:
void addValue(const T& t) {
values_.push_back(t);
}
void print() {
typedef boost::integral_constant<bool,
::boost::is_pointer<T>::value> truth_type;
for (unsigned int i = 0; i < values_.size(); i++)
doPrint(values_[i], truth_type());
}
private:
void doPrint(const T& t, const boost::false_type&) {
cout << "Not pointer. Value:" << t << endl;
}
void doPrint(const T& t, const boost::true_type&) {
cout << "Pointer. Value: " << *t << endl;
}
std::vector<T> values_;
};
int main() {
CVector<int> integers;
integers.addValue(3);
integers.addValue(5);
integers.print();
CVector<int*> pointers;
int three = 3;
int five = 5;
pointers.addValue(&three);
pointers.addValue(&five);
pointers.print();
}
I don't think templates are quite that flexible.
A very brute force approach would be to specialize for all of your pointer types...which defeats the problem of using templates.
Could you have a different CVector class that is used only for vectors of pointers?
I agree with rlbond's answer. I have modified it a little bit to suit your need. CVector can be a derived class of the CVector itself. You can then use different members and functions for it.
#include <iostream>
#include <string>
template <class T>
class CVector
{
public:
void test() { std::cout << "Not wrapped!\n"; }
void testParent() { std::cout << "Parent Called\n";}
};
template <class T>
class CVector<T*>:
public CVector<T>
{
public:
void test(std::string msg) { std::cout << msg; testParent(); }
};
int main()
{
CVector<int> i;
CVector<double> d;
CVector<int*> pi;
CVector<double*> pd;
i.test();
d.test();
pi.test("Hello\n");
pd.test("World\n");
system("pause");
}

Best way to for C++ types to self register in a list?

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.