I'm very familiar with Qt and I know that we cannot have a similar synthax because we don't have the MOC part here. However I'm trying to have a signal creation management to simplify the declaration of a signal and the connection to it, inside my classes.
this is schematicly what I'm doing now
class Foo
{
public:
void connectMove(boost::signal<void(int)>::slot_type slot)
void connectRotate(boost::signal<void(double)>::slot_type slot)
private:
boost::signal<void(int)> m_signalMove;
boost::signal<void(double)> m_signalRotate;
};
and this is basicaly what I would like to do (UPPERCASE = missing part)
class SignalManager
{
public:
typedef boost::unrodered_map<std::string, GENERIC_SIGNAL *> MapSignal;
public:
template <typename Sig>
bool connect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
{
// simplyfied... :
(*m_mapSignal.find(strSignalName))->connect(slot);
}
template <typename Sig>
bool disconnect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
{
// simplyfied... :
(*m_mapSignal.find(strSignalName))->disconnect(slot);
}
protected:
bool call(const std::string& strSignalName, SIGNAL_ARGS)
{
(*m_mapSignal.find(strSignalName))(SIGNAL_ARGS);
}
template <typename Sig>
void delareSignal(const std::string& strSignalName)
{
m_mapSignals.insert(MapSignal::value_type(strSignalName, new boost::signal<Sig>()));
}
void destroySignal(const std::string& strSignalName)
{
// simplyfied... :
auto it = m_mapSignal.find(strSignalName);
delete *it;
m_mapSignal.erase(it);
}
private:
MapSignal m_mapSignals;
};
class Foo : public SignalManager
{
public:
Foo(void)
{
this->declareSignal<void(int)>("Move");
this->declareSignal<void(double)>("Rotate");
}
};
class Other : public boost::signals::trackable
{
public:
Other(Foo *p)
{
p->connect("Move", &Other::onMove);
p->connect("Rotate", &Other::onRotate);
}
void onMove(int i)
{
/* ... */
}
void onRotate(double d)
{
/* ... */
}
};
I think I could resolve the "SIGNAL_ARGS" part with boost::functions_traits<>, but i don't know how to go around the abstract signal type.
1/ Is what I want even possible ?
2/ Is this a good approach ? (I know I will have some overhead due to the unordered_map.find, esspecily when I use this->call("signalname", ...), but I think it shouldn't be too significant)
3/ If this is not possible or not a good approach, do you have any other suggestions ?
I resolved my problem by wrapping boost::signals and having a boost::shared_ptr<IWrapperSignal> instead of my GENERIC_SIGNAL.
The arguments probnlem was also resolved using boost::function_traits<T>::arg_type.
I don't know if it's the best way to do that, but it's working fine, and it is more simple for the user to declare signals in the classes that inherit this SignalManager.
Related
I am just thinking about a way to check an object to be valid in a automated way.
I have a couple of hardware related objects (like class A), which can be deleted by external (physical) events.
To detect this I have used shared/weak pointer. But now I am struggling with the checking of the weak pointer. Since this is done in the same way for each member function for many objects, I am currently searching for a way to do this with less redundant code.
In addition I am writing a library and do not want the user to handle this (simply return the weak pointer to the user to handle it by himself is therefor no option)
My best guess is shown below. My problem is, I could not find a way to generate the member functions (func1, and many more ...) automatically within the template. Doing it by myself would result in lot of redundant code for every member function to be validated (and there are a lot)
Each member function of A (and many more other objects) shall be wrapped by a function doing the validation shown below. This is same for all member functions and done for many classes which can be used as type for the Validator.
Does anyone has an idea how to solve this? Maybe there are other (better) ways to solve this.
Many thanks for your help.
Some constraints:
Only C++11 possible,
No exceptions
class A {
public:
void func1() {}
//many more functions
};
template<typename T>
class Validator
{
//has to be done for all functions of A
void func1()
{
if (!wptr.expired())
{
wptr.lock()->func1();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
I would protect the full user function call:
class A {
public:
void func1() {}
//many more functions
};
template <typename T>
class Validator
{
public:
#if 1 // template way, but no-expressive signature
template <typename F>
void do_job(F f)
#else // type-erasure way, expressive, but with some overhead
void do_job(std::function<void (T&)> f)
#endif
{
auto t = wptr.lock();
if (t) {
f(*t);
} else {
errorHandling();
}
}
private:
void errorHandling();
private:
std::weak_ptr<T> wptr;
};
So user might chain call:
Validator<A> val;
val.do_job([](A& a)
{
a.func1();
a.func2();
});
If the caller can live with clunky syntax you can use member function pointers:
#include <memory>
#include <iostream>
class A {
public:
void func1() {
std::cout << "hello func1\n";
}
};
template<typename T>
class Validator
{
public:
Validator(std::shared_ptr<T> p) : wptr(p) {}
template <typename MemFun>
void call(MemFun mf) {
if (!wptr.expired())
{
(wptr.lock().get()->*mf)();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
int main() {
auto x = std::make_shared<A>();
Validator<A> v{x};
v.call(&A::func1);
}
I have a class named MyClass that is subscribed by another class. When some events happen, MyClass should notify subscribers.
I'm trying to use template for the subscriber's type. Because I don't want to let others(who are in charge of subscriber class) need to care about modifying MyClass for subscribing.
So I've written codes below,
class MyClass {
public:
template<typename T>
void subscribeEvents(const T &controller)
{
m_subscriber = static_cast<T*>(m_subscriber);
m_subscriber = &controller;
}
void notifyPositionChanged(const long &position) const {
(m_subscriber)->onPositionChanged(position);
}
private:
void m_subscriber; // will be changed to array or something else
}
Actually the controller object has a method namedonPositionChanged.
But as you know, it's not compiled for this line.
(m_subscriber)->onPositionChanged(position);
Now I understand why it's an error, but the problem is that I don't know how to modify codes or change my design. Please let me know what I'm missing and misunderstanding. Thanks in advance.
You dont need to use template for this. Just use a base class for your subscribers. And MyClass operate on your base class
class ISubscribe {
public:
virtual void onPositionChanged(const long &position) = 0;
};
class MyClass {
public:
void subscribeEvents(ISubscribe *controller)
{
m_subscriber = controller;
}
void notifyPositionChanged(const long &position) const {
(m_subscriber)->onPositionChanged(position);
}
private:
ISubscribe *m_subscriber; // will be changed to array or something else
};
class SampleSubscriber : public ISubscribe {
public :
void onPositionChanged(const long &position) override{
...
}
};
void main() {
SampleSubscriber s;
MyClass m;
m.subscribeEvents(&s);
....
}
You need to define a common interface to all your subscribers, then use this interface as m_subscriber's type. Savagely casting whatever parameter you receive to a defined type will lead only to undefined behaviors.
Use std::function:
class MyClass {
public:
template<typename CALLBACK>
void subscribeEvents(CALLBACK &&controller)
{
m_subscriber = std::forward<CALLBACK>(controller);
}
void notifyPositionChanged(const long &position) const
{
if (m_subscriber)
m_subscriber(position);
}
private:
std::function<void(const long&)> m_subscriber;
}
This gives the subscriber full freedom of what it wants to subscribe. For example:
there.subscribeEvents([this](const long &pos) { handlePosChange(pos); }
Lets say I have an array of functions :
name::Function _actions[10];
The name::Function is just a wrapper for std::function:
class Function{
public :
std::function<void(float dt)> Function;
void exec(float dt){
Function(dt);
}
};
And now I have a function to make it generic so it can bind any classes functions :
template<class T>
void bindFunction(int action,void (T::*function)(float) , T* classPtr)
{
_actions[action] = boost::bind(&function, this, boost::placeholders::_1);
}
And want to use it inside a class that inherits this method (the base class is generic but I think it shouldn´t be a problem)
DefaultMovableEntity()
{
bindFunction(1, &DefaultMovableEntity::func1, this);
}
void func1(float dt)
{
//Code
}
However I keep getting erros :
What is the main problem? I thought im doing everything right. Thanks.
Edit1
After removing the & from the function and replacing this got following error:
There are several problems with your code:
You can't assign your bind result to the array since your array member type is Function, not std::function.
You need to remove & as said before in comments.
Your member named Function is same as class name so compiler may think you are trying to call class constructor.
The following code should work:
class Function {
public:
std::function<void(float)> func;
void exec(float dt) {
func(dt);
}
};
and bindFunction code:
template<class T>
void bindFunction(int action, void (T::*function)(float), T* classPtr)
{
_actions[action].func = boost::bind(function, classPtr, boost::placeholders::_1);
}
However I would suggest slight improvement of Function class so that it doesn't expose its members directly:
class Function
{
private:
std::function<void(float)> func;
public:
Function() = default;
Function(std::function<void(float)> f) : func(f) { }
void exec(float dt) {
func(dt);
}
};
And corresponding change of your bindFunction:
template<class T>
void bindFunction(int action, void (T::*function)(float), T* classPtr)
{
_actions[action] = Function(boost::bind(function, classPtr, boost::placeholders::_1));
}
Understandably, functions can not be both templated and virtual.
But there may be a super smart design pattern out there that would do.
My goal is to have a function which looks like as :
void configure(const Configuration &config){
double stuff = config.get<double>("stuff");
int thing = config.get<int>("thing");
// rest of the code
}
Ideally, I could pass various configuration object, e.g. object that read from a file or from a database.
Here a (stripped to minimum) example of a concrete config class using yaml-cpp (I guess understandable even if you do not know yaml-cpp):
class YAML_config : public Configuration {
public:
YAML_config(std::string file_path){
this->node = YAML::LoadFile(file_path);
}
template<typename T> T get(std::string key){
return this->node[key].as<T>();
}
private:
YAML::Node node;
Question is: what would be the suitable code for the class Configuration ?
Here some invalid code that shows the intend:
class Configuration {
virtual template<typename T> T get(std::string key)=0;
}
If all this is just a bad start, any other approach I should look into ? I checked for "type erasure", but that did not seem to help (or did I miss something ?)
It looks like you have a small-ish set of possible types, so I suggest a set of virtual functions grouped together with a non-virtual dispatching template:
template <class T>
struct tag { };
class Configuration {
public:
template <class T>
T get(std::string key) {
return get_(tag<T>{}, std::move(key));
}
protected:
virtual int get_(tag<int>, std::string key) = 0;
virtual double get_(tag<double>, std::string key) = 0;
virtual std::string get_(tag<std::string>, std::string key) = 0;
};
class YAML_config : public Configuration {
int get_(tag<int>, std::string key) override { /* ... */ }
double get_(tag<double>, std::string key) override { /* ... */ }
std::string get_(tag<std::string>, std::string key) override { /* ... */ }
};
Usage:
YAML_config cfg;
auto s = cfg.get<int>("hello");
See it live on Coliru
But we lost the ability to declare YAML_config::get as a template -- types aside, the implementations are all the same, but we can't override a virtual function with a template.
So, now that we bridged the gap from templates to virtual functions to achieve polymorphism, let's bridge the gap from virtual functions back to templates to get our nice API back. This can be done by slotting in a CRTP between the Configuration and YAML_config classes: its role will be to generate the overriden functions.
Note: the get_ virtual functions are now called getBridge. I have added a dash of macros to cut down on repetition. These can be further factored out with Boost.PP, for example.
class ConfigurationBase {
// ...
#define DECLARE_CONFIG_BRIDGE(T) \
virtual T getBridge(tag<T>, std::string key) = 0;
DECLARE_CONFIG_BRIDGE(int)
DECLARE_CONFIG_BRIDGE(double)
DECLARE_CONFIG_BRIDGE(std::string)
#undef DECLARE_CONFIG_BRIDGE
};
template <class Derived>
class Configuration : public ConfigurationBase {
// Hide ConfigurationBase::get so we don't get
// infinite recursion if we forget an implementation
// in the derived class.
template <class>
void get(...) = delete;
#define OVERRIDE_CONFIG_BRIDGE(T) \
T getBridge(tag<T>, std::string key) override { \
return dThis()->template get<T>(std::move(key)); \
}
OVERRIDE_CONFIG_BRIDGE(int)
OVERRIDE_CONFIG_BRIDGE(double)
OVERRIDE_CONFIG_BRIDGE(std::string)
#undef OVERRIDE_CONFIG_BRIDGE
Derived *dThis() {
return static_cast<Derived*>(this);
}
};
class YAML_config : public Configuration<YAML_config> {
public:
template <class T>
T get(std::string) {
return {};
}
};
See it live on Coliru
I have adapted my answer to a similar question from earlier today which uses type erasure and RTTI to get the effect of a virtual templated function. As I noted there, Boost.TypeIndex can be used if you cannot or do not want to use RTTI.
The basic implementation looks something like this (just fill in your YAML library stuff):
#include <functional>
#include <typeindex>
#include <unordered_map>
class config {
public:
template <typename T>
T get(char const* key) {
T value = {};
auto it = getters.find(type_index<T>());
if (it != getters.end()) {
it->second(&value, key);
}
return value;
}
protected:
template <typename T, typename Getter>
void register_getter(Getter getter) {
getters[type_index<T>()] = [getter](void* value, char const* key) {
*static_cast<T*>(value) = getter(key);
};
}
private:
template <typename T>
static std::type_index type_index() {
return std::type_index(typeid(std::remove_cv_t<T>));
}
std::unordered_map<std::type_index, std::function<void (void*, char const*)>> getters;
};
Usage would look like this (note that you could use composition instead of inheritance if you don't actually need config to be a base class):
#include <iostream>
class yaml_config : public config {
public:
yaml_config() {
register_getter<int>([](char const* key) {
return 42;
});
register_getter<float>([](char const* key) {
return 3.14f;
});
}
};
int main() {
yaml_config cfg;
std::cout << cfg.get<int>("foo") << "\n";
std::cout << cfg.get<float>("bar") << "\n";
std::cout << cfg.get<short>("baz") << "\n";
}
Output:
42
3.14
0
In this particular implementation, T must be default constructible; if this is unacceptable, you could use std::any instead of void*. In addition, a default value is returned in the case where an appropriate getter is not registered. You may want to throw an exception, or return a std::optional<T> or std::pair<T, bool>, to distinguish these cases from a default value actually being mapped to a specific key.
This solution has the advantage that sub-classes can register getters for any type. However, there are certainly more efficient solutions if you know the subset of types that config::get<T> needs to work with.
Say I have listeners built in C++98, they are abstract and must for example implement ActionPerformed. In C++0x is there a way to do similar to Java:
button.addActionListener(new ActionListener() {
public void actionPerfored(ActionEvent e)
{
// do something.
}
});
Thanks
Not exactly, but you can do something close with Lambdas.
i.e.:
class ActionListener
{
public:
typedef std::function<void(ActionEvent&)> ActionCallback;
public:
ActionListener( ActionCallback cb )
:_callback(cb)
{}
void fire(ActionEvent& e )
{
_callback(e);
}
private:
ActionCallback _callback;
};
..
button.addActionListener( new ActionListener(
[]( ActionEvent& e )
{
...
}
));
No you can't do that.
If you give up on "similar to Java", though, and just use a functor, you'll find C++11 lambdas very helpful.
This is C++, not Java, so writing C++ like Java won't work well.
Anyway, you could create an adaptor function. Suppose
typedef int ActionEvent; // <-- just for testing
class ActionListener
{
public:
virtual void actionPerformed(const ActionEvent& event) = 0;
};
Then we could write a templated subclass of ActionListener that wraps a function object:
#include <memory>
template <typename F>
class ActionListenerFunctor final : public ActionListener
{
public:
template <typename T>
ActionListenerFunctor(T&& function)
: _function(std::forward<T>(function)) {}
virtual void actionPerformed(const ActionEvent& event)
{
_function(event);
}
private:
F _function;
};
template <typename F>
std::unique_ptr<ActionListenerFunctor<F>> make_action_listener(F&& function)
{
auto ptr = new ActionListenerFunctor<F>(std::forward<F>(function));
return std::unique_ptr<ActionListenerFunctor<F>>(ptr);
}
and then use make_action_listener to wrap a lambda, e.g ( http://ideone.com/SQaLz ).
#include <iostream>
void addActionListener(std::shared_ptr<ActionListener> listener)
{
ActionEvent e = 12;
listener->actionPerformed(e);
}
int main()
{
addActionListener(make_action_listener([](const ActionEvent& event)
{
std::cout << event << std::endl;
}));
}
Note that this is far from idiomatic C++, where in addActionListener() you should simply take a const std::function<void(const ActionEvent&)>&, or even a template parameter for maximum efficiency, and supply the lambda directly.
I think we can do this in C++ using lambdas
button.addActionListener([]()->ActionListener*{ struct A: ActionListener {
void actionPerfored(ActionEvent e)
{
// do something.
}
}; return new A;}());
It should be easy to wrap this up in a macro.