Reducing the number of overloaded functions and constructors - c++

Consider the following class definition:
class Car : public Vehicle {
private:
TouchScreen a;
RadioAntenna b;
Blah c;
public:
Car(TouchScreen &a1) {
a = a1; //copy ctor
}
Car(RadioAntenna &b1) {
b = b1;
}
Car(Blah &c1) {
c = c1;
}
void update(Touchscreen &a1) {
a.update(a1);
}
void update(RadioAntenna &b1) {
b.update(b1);
}
void update(Blah &c1) {
c.update(c1);
}
}
class Fleet {
private:
std::map<int, Car> _fleet; //vehicle number, Car
public:
template <typename T>
void update(int vehicle_num, T &t) {
auto it = _fleet.find(vehicle_num);
if (it == _fleet.end()) {
_fleet[vehicle_num] = Car(t);
}
else {
it->second.update(t);
}
}
}
Fleet contains a collection of cars. If you want to update a specific car's member variable,
Fleet f;
f.update<TouchScreen>(4, a1);
f.update<Blah>(10, c1);
In the future, more class instances can be defined inside Car. Is there a way to reduce the number of overloaded Constructor and update() functions? Using templates maybe? I feel it looks ugly, design wise, using so many overloaded functions.

My idea is to use std::any for doing it. Assumed you have only one instance for each type inside Car class.
Here is my solution:
class Car : public Vehicle {
private:
std::unordered_map<std::string, std::any> components;
public:
Car(std::any &obj) {
std::string typeName(obj.type().name());
components.insert(make_pair(typeName, obj));
}
template<typename T>
void update(T& found, T &a1)
{
(std::any_cast<T>(found)).update(std::any_cast<T>(a1));
}
void update(std::any &a1) {
std::string typeName(a1.type().name());
std::any found = components.find(typeName);
if (found != components.end())
{
if (typeName == std::string(typeid(TouchScreen).name())
{
update<TouchScreen>(found.second, a1);
}
else if (typeName == std::string(typeid(RadioAntenna ).name())
{
update<RadioAntenna>(found.second, a1);
}
else if (typeName == std::string(typeid(Blah ).name())
{
update<Blah>(found.second, a1);
}
}
}
}

An alternative code could be:
void Car::update(Touchscreen* a1=nullptr, RadioAntenna* b1=nullptr, Blah* c1=nullptr ) {
if(a1) a.update(*a1);
if(b1) b.update(*b1);
if(c1) c.update(*c1);
}

Related

dynamically call same named function with different return type

I have a situation here...
I want to design a Factory where I can call a function with same name and no parameters but return different data Types. Based on the SubClassName I need to instantiate the Object.
Need help or lead on any design pattern to follow?
EDIT:
An abstract pseudo code...
class parent{
public:
virtual string getName() = 0;
//some virtual function.. not sure how to design. As the return type is dynamic.
*** getValue(){}
};
class A : public parent{
int x;
public:
virtual string getName(){ return "A";}
virtual int getValue(){retun x;}
};
class B : public parent{
string s;
public:
virtual string getName(){ return "B";}
virtual string getValue(){ return s;}
};
void main(){
string callingClass = "B";
parent * arrayPtrs[2];
arrayPtrs[0] = new A;
arrayPtrs[1] = new B;
for (loop through array, through iterator i){
if(arrayPtrs[i]->getName == callingClass ){
cout<<arrayPtrs[i]->getValue;
}
}
}
In C++ a function can only have one return type at a time, and you cannot change that dynamically.
However - as suggested by #mch - you can use template specializations. Keep in mind though, that this method is not dynamic. Your functions will be generated at compile time.
If I understood your question correctly, maybe this can be of help.
class MyObject1
{
//...
};
class MyObject2
{
//...
};
template<typename T>
struct Factory
{
constexpr static T gen();
};
template<>
struct Factory<MyObject1>
{
constexpr static MyObject1 gen()
{
return MyObject1(/*... whatever parameters you see fit ...*/);
}
};
template<>
struct Factory<MyObject2>
{
constexpr static MyObject2 gen()
{
return MyObject2(/*... whatever parameters you see fit ...*/);
}
};
int main()
{
auto myObj = Factory<MyObject1>::gen();
return 0;
}
Although this method seems fairly useless to me. You could simply call the desired constructor instead of this.
But then again, I'm not sure if this is what you thought of. If I made any mistakes please feel free, to correct me. I'll try to edit my answer best as I can.
EDIT:
To keep the virtual functionality too, the only way I can think of is type erasure: see https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Erasure
The closest I could get to what you've asked for is this:
#include <iostream>
#include <string>
#include <any>
class parent {
public:
// you can use this too but I think type checking is more handy
// see in main function
/* virtual std::string getName() const = 0; */
virtual std::any getValue() const = 0;
};
class A : public parent {
public:
typedef int value_type;
private:
value_type x;
public:
A(value_type x) :
x(x)
{}
/* virtual std::string getName() const override { return "A"; } */
virtual std::any getValue() const override
{ return this->x; }
};
class B : public parent {
public:
typedef std::string value_type;
private:
value_type s;
public:
B(const value_type& s) :
s(s)
{}
/* virtual std::string getName() const override { return "B"; } */
virtual std::any getValue() const override
{ return this->s; }
};
int main(){
using callingClass = A;
parent* arrayPtrs[2];
arrayPtrs[0] = new A(42);
arrayPtrs[1] = new B("my string");
for (unsigned i = 0; i < sizeof(arrayPtrs) / sizeof(parent*); ++i)
{
// Note:
// dynamic cast will return nullptr if $callingClass
// is not a derived class
if (dynamic_cast<callingClass*>(arrayPtrs[i]))
std::cout << std::any_cast<callingClass::value_type>(arrayPtrs[i]->getValue()) << std::endl;
}
return 0;
}
I hope this one helps.
Note, that I used dynamic_cast to check the correct type. If you know a better solution, you can use that, too. But under these circumstances I couldn't think of any better.
EDIT2:
#include <iostream>
#include <string>
#include <tuple>
class some
{
using id = size_t;
template<typename T>
struct type { static void id() { } };
template<typename T>
static id type_id() { return reinterpret_cast<id>(&type<T>::id); }
template<typename T>
using decay = typename std::decay<T>::type;
template<typename T>
using none = typename std::enable_if<!std::is_same<some, T>::value>::type;
struct base
{
virtual ~base() { }
virtual bool is(id) const = 0;
virtual base *copy() const = 0;
} *p = nullptr;
template<typename T>
struct data : base, std::tuple<T>
{
using std::tuple<T>::tuple;
T &get() & { return std::get<0>(*this); }
T const &get() const& { return std::get<0>(*this); }
bool is(id i) const override { return i == type_id<T>(); }
base *copy() const override { return new data{get()}; }
};
template<typename T>
T &stat() { return static_cast<data<T>&>(*p).get(); }
template<typename T>
T const &stat() const { return static_cast<data<T> const&>(*p).get(); }
template<typename T>
T &dyn() { return dynamic_cast<data<T>&>(*p).get(); }
template<typename T>
T const &dyn() const { return dynamic_cast<data<T> const&>(*p).get(); }
public:
some() { }
~some() { delete p; }
some(some &&s) : p{s.p} { s.p = nullptr; }
some(some const &s) : p{s.p->copy()} { }
template<typename T, typename U = decay<T>, typename = none<U>>
some(T &&x) : p{new data<U>{std::forward<T>(x)}} { }
some &operator=(some s) { swap(*this, s); return *this; }
friend void swap(some &s, some &r) { std::swap(s.p, r.p); }
void clear() { delete p; p = nullptr; }
bool empty() const { return p; }
template<typename T>
bool is() const { return p ? p->is(type_id<T>()) : false; }
template<typename T> T &&_() && { return std::move(stat<T>()); }
template<typename T> T &_() & { return stat<T>(); }
template<typename T> T const &_() const& { return stat<T>(); }
template<typename T> T &&cast() && { return std::move(dyn<T>()); }
template<typename T> T &cast() & { return dyn<T>(); }
template<typename T> T const &cast() const& { return dyn<T>(); }
template<typename T> operator T &&() && { return std::move(_<T>()); }
template<typename T> operator T &() & { return _<T>(); }
template<typename T> operator T const&() const& { return _<T>(); }
};
using any = some;
class parent {
public:
// you can use this too but I think type checking is more handy
/* virtual std::string getName() const = 0; */
virtual any getValue() const = 0;
};
class A : public parent {
public:
typedef int value_type;
private:
value_type x;
public:
A(value_type x) :
x(x)
{}
/* virtual std::string getName() const override { return "A"; } */
virtual any getValue() const override
{ return this->x; }
};
class B : public parent {
public:
typedef std::string value_type;
private:
value_type s;
public:
B(const value_type& s) :
s(s)
{}
/* virtual std::string getName() const override { return "B"; } */
virtual any getValue() const override
{ return this->s; }
};
int main(){
using callingClass = A;
parent* arrayPtrs[2];
arrayPtrs[0] = new A(42);
arrayPtrs[1] = new B("my string");
for (unsigned i = 0; i < sizeof(arrayPtrs) / sizeof(parent*); ++i)
{
// Note:
// dynamic cast will return nullptr if $callingClass
// is not a derived class
if (dynamic_cast<callingClass*>(arrayPtrs[i]))
std::cout << arrayPtrs[i]->getValue()._<callingClass::value_type>() << std::endl;
}
return 0;
}
This snipped is in case you cannot use C++17 features, and is based on:
any class

Simulate constructor behaviour for virtual methods

I am currently working on a small private project using C++ i came up with the following structure:
#include <iostream>
class A
{
std::vector<int> vec;
protected:
virtual bool onAdd(int toAdd) {
// should the 'adding' be suppressed?
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return false;
}
public:
void add(int i) {
if(!onAdd(i)) {
// actual logic
vec.push_back(i);
}
}
};
class B : public A
{
protected:
bool onAdd(int toAdd) override {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
In this example onAdd is basically meant to be a callback for add, but in a more polymorphic way.
The actual problem arises when a class C inherits from B and wants to override onAdd too. In this case the implementation in B will get discarded (i.e. not called) when calling C::add. So basically what I would like to achieve is a constructor-like behaviour where I am able to override the same method in different positions in the class hierarchy and all of those getting called.
My question now is: Is there a possibility/design to achieve this? I am sure that it wouldn't be as easy as cascading constructors, though.
Note: Don't focus too much on the add example. The question is about the callback like structure and not if it makes sense with an add.
I would just call my parents onAdd()
bool C::onAdd(int toAdd) {return my_answer && B::onAdd(toAdd);}
This can be a little confusing if you're expecting other developers to inherit from your base class. But for small private hierarchies it works perfectly.
I sometimes include a using statement to make this more explicit
class C : public B
{
using parent=B;
bool onAdd(int toAdd) override {return my_answer && parent::onAdd(toAdd);}
};
struct RunAndDiscard {
template<class Sig, class...Args>
void operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return;
for (auto* i = start; i != (finish-1); ++i) {
(*i)(args...);
}
(*(finish-1))(std::forward<Args>(args)...);
}
};
template<class Sig, class Combine=RunAndDiscard>
struct invokers {
std::vector<Sig*> targets;
template<class...Args>
decltype(auto) operator()(Args&&...args)const {
return Combine{}( targets.data(), targets.data()+targets.size(), std::forward<Args>(args)... );
}
};
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
This creates a per-instance table of things to do onAdd.
Creating a per-class table is harder; you need to chain your table with your parent type's table, which requires per-class boilerplate.
There is no way to get the C++ compiler to write either the per-instance version, or the per-class version, without doing it yourself.
There are C++20 proposals involving reflection and reification, plus the metaclass proposal, which may involve automating writing code like this (on both a per-instance and per-class basis).
Here is a live example of this technique being tested:
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
class A {
std::vector<int> vec;
protected:
invokers<bool(A*, int), AndTogetherResultWithShortCircuit> onAdd;
public:
void add(int i) {
if (!onAdd(this, i)) {
vec.push_back(i);
}
}
};
class B : public A
{
public:
B() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "B::onAdd(" << x << ")" << std::endl;
return x%2;
});
}
};
class C : public B
{
public:
C() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "C::onAdd(" << x << ")" << std::endl;
return false;
});
}
};
When you want to write your own OO-system, you can in C++, but C++ doesn't write it for you.
If you want a generic solution perhaps you could use CRTP with variadic templates instead of runtime polymophism.
Taking inspiration from this answer and this answer:
template<class... OnAdders> class A : private OnAdders... {
std::vector<int> vec;
template<class OnAdder>
bool onAdd(int toAdd){
return static_cast<OnAdder*>(this)->onAdd(toAdd);
}
template<typename FirstOnAdder, typename SecondOnAdder, class... RestOnAdders>
bool onAdd(int toAdd){
if (onAdd<FirstOnAdder>(toAdd))
return true;
return onAdd<SecondOnAdder, RestOnAdders...>(toAdd);
}
public:
void add(int i) {
if (onAdd<OnAdders...>(i))
return;
// actual logic
vec.push_back(i);
}
};
class B {
public:
bool onAdd(int toAdd) {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
Which you could use like:
A<B,C> a;
a.add(42);
Live demo.
The following solution uses std::function to add each callback during each constructor:
#include <iostream>
#include <vector>
#include <functional>
class A
{
std::vector<int> vec;
protected:
bool onAdd(int toAdd)
{
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return true;
}
// vector of callback functions. Initialized with A::onAdd() callback as the first entry
std::vector<std::function<bool(int)>> callbacks{{[this](int toAdd){return onAdd(toAdd); }}};
public:
void add(int i)
{
for(auto& callback : callbacks) {
if(!callback(i))
return;
}
// actual logic
vec.push_back(i);
}
};
class B : public A
{
public:
B()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return true;
}
};
class C : public B
{
public:
C()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some C specific checks
std::cout << "C::onAdd()" << std::endl;
// must also call B::onAdd()
return true;
}
};
int main()
{
C c;
c.add(5);
}
Prints:
A::onAdd()
B::onAdd()
C::onAdd()

Implementing the observer pattern using CRTP and 'anonymous types/template'

I'm developing a library that parses a certain XML file (using RapidXML) and returns an object of mine, containing that file data. That XML file is created by someone else's application. I needed to use the observer pattern because speed is extremely crucial, for example:
Suppose a file has 10.000 tag and its child nodes. In a simple parser, they would be added to a std::vector in the order they were found. Then, after the file was parsed, we would need to iterate over the 10.000 values AGAIN and do whatever we want with them.
By using the observer pattern, I allow external observers (whichever class that wants to observe and be notified about each fetched node has to inherit from AbstractObserver that comes with my library, and implement his functions) to be a part of the parsing process without the need to iterate X times again over the parsed nodes. HOWEVER... There are multiple kinds of nodes, for example: tileset, layer, imagelayer and so on (being necessary multiple onObserved and notify functions for its corresponding node, according to the Observer/Subject pattern, probably having a lot of 'duplicated' code - NOTE: inheritance is not used. See bellow a 'bad' example). I could simply make the nodes inherit from some sort of BaseNode class, but I dont want to use inheritance here since I dont want to deal with pointers. Instead, I'm using enums to type the nodes and thats where my problem lies.
/* ################## ABSTRACT OBSERVER #################### */
// Implements the observer pattern, using the CRTP pattern
template<class ConcreteObserver>
class AbstractObserver
{
public:
virtual ~AbstractObserver() { }
template<class Attribute>
inline void onObserved(Attribute attribute) {
// This requires ConcreteObserver to have a method onObservedImpl<Attribute>
static_cast<const ConcreteObserver*>(this)->onObservedImpl(attribute);
}
};
/* ################## ABSTRACT SUBJECT #################### */
class AbstractSubject
{
public:
virtual ~AbstractSubject() { }
// ???????
inline void attach(AbstractObserver<??????>* observer) {
m_observers.push_back(observer);
}
// ???????
inline void detatch(AbstractObserver<??????>* observer) {
auto& it = std::find(m_observers.begin(), m_observers.end(), observer);
// Remove the observer from the list, if it was observing
if (it != m_observers.end())
m_observers.erase(it);
}
protected:
template<typename Attribute>
void notify(Attribute& attribute) {
for (auto* observer : m_observers)
observer->onObserved(attribute)
}
private:
// ???????
std::vector<AbstractObserver<??????>*> m_observers;
};
/* ################## CONCRETE OBSERVER #################### */
class SomeConcreteObserver : public AbstractObserver<SomeConcreteObserver>
{
public:
// The CRTP 'virtual' function implementation
template<class Attribute>
void onObservedImpl(Attribute attribute)
{
// Filter the attribute and use it accordingly
switch (attribute.type)
{
// ....
}
}
};
/* ################## CONCRETE SUBJECT #################### */
class Parser : public AbstractSubject
{
public:
void parse(/* params */)
{
Foo f;
notify<Foo>(f);
// Later on....
Bar b;
notify<Bar>(b);
}
};
As we can see, I'm using the CRTP as well, since I need 'templated virtual functions', which is impossible to achieve otherwise. Since the AbstractObserver needs a type (because of the CRTP), I can't properly use them in the AbstractSubject class (see above). Is it even possible to use annonymous templates just like Java, or something like that? I believe this WOULD do the job.
Here is the implementation of a 'bad' example I thought of, but this is the best I could come up with for this situation:
// Remove the CRTP
class AbstractObserver
{
public:
virtual ~AbstractObserver() { }
virtual void onNodeA(NodeA n) = 0;
virtual void onNodeB(NodeB n) = 0;
virtual void onNodeC(NodeC n) = 0;
virtual void onNodeD(NodeD n) = 0;
virtual void onNodeE(NodeE n) = 0;
// .....
};
class AbstractSubject
{
public:
// ....
protected:
void notifyNodeA(NodeA n) {
for (auto* observer : m_observers)
observer->onNodeA(n);
}
void notifyNodeB(NodeB n) {
for (auto* observer : m_observers)
observer->NodeB(n);
}
void notifyNodeC(NodeC n) { }
void notifyNodeD(NodeD n) { }
void notifyNodeE(NodeE n) { }
// ....
private:
std::vector<Observer*> m_observers;
};
The solution has to use C++11 or bellow and no boost.
Solution #1: Quite wet but simple
#include <vector>
#include <algorithm>
#include <iostream>
template<typename TAttribute>
class Observer
{
public:
virtual void Observe(TAttribute& attribute) = 0;
virtual ~Observer() = default;
};
template<typename TAttribute>
class OutputtingObserver : public Observer<TAttribute>
{
public:
void Observe(TAttribute& attribute)
{
std::cout << attribute << std::endl;
}
~OutputtingObserver() = default;
};
template<typename TAttribute>
class Subject
{
private:
std::vector<Observer<TAttribute>*> mutable m_observers;
public:
void Attach(Observer<TAttribute>& observer) const
{
m_observers.push_back(&observer);
}
void Detach(Observer<TAttribute>& observer) const
{
m_observers.erase(std::remove(m_observers.begin(), m_observers.end(), &observer), m_observers.end());
}
void Notify(TAttribute& attribute)
{
for (auto observer : m_observers)
observer->Observe(attribute);
}
};
class NodeA
{
public:
friend std::ostream& operator<<(std::ostream& o, const NodeA& node)
{
return o << "a";
}
};
class NodeB
{
public:
friend std::ostream& operator<<(std::ostream& o, const NodeB& node)
{
return o << "b";
}
};
class Parser
{
private:
Subject<NodeA> m_subjectA;
Subject<NodeB> m_subjectB;
public:
void Parse()
{
auto a = NodeA();
auto b = NodeB();
m_subjectA.Notify(a);
m_subjectB.Notify(b);
}
void Attach(Observer<NodeA>& observer)
{
m_subjectA.Attach(observer);
}
void Attach(Observer<NodeB>& observer)
{
m_subjectB.Attach(observer);
}
};
int main()
{
auto observerA = OutputtingObserver<NodeA>();
auto observerB = OutputtingObserver<NodeB>();
auto parser = Parser();
parser.Attach(observerA);
parser.Attach(observerB);
parser.Attach(observerA);
parser.Parse();
return 1;
}
You would need to use composition here and have a subject for each type of node. However, this is compile-time validated so I'd prefer this to the second version.
Solution #2: Dynamic and closer to what you want
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <iostream>
class ObserverBase
{
public:
virtual ~ObserverBase() = default;
};
template<typename TAttribute>
class Observer : public ObserverBase
{
public:
virtual void Observe(TAttribute& attribute) = 0;
};
template<typename TAttribute>
class OutputtingObserver : public Observer<TAttribute>
{
public:
void Observe(TAttribute& attribute)
{
std::cout << attribute << std::endl;
}
~OutputtingObserver() = default;
};
template<typename TKey>
class Subject
{
private:
using ObserverList = std::vector<ObserverBase*>;
using ObserverMap = std::unordered_map<TKey, ObserverList>;
ObserverMap mutable m_observers;
public:
void Attach(TKey key, ObserverBase& observer) const
{
auto itr = m_observers.find(key);
if (itr == m_observers.end())
{
m_observers.emplace(std::make_pair(key, ObserverList { &observer }));
return;
}
itr->second.push_back(&observer);
}
void Detach(ObserverBase& observer) const
{
m_observers.erase(std::remove(m_observers.begin(), m_observers.end(), &observer), m_observers.end());
}
template<TKey key, typename TAttribute>
void Notify(TAttribute& attribute)
{
auto itr = m_observers.find(key);
if (itr == m_observers.end())
return;
for (auto observer : itr->second)
dynamic_cast<Observer<TAttribute>*>(observer)->Observe(attribute);
}
};
enum class NodeType
{
TypeA,
TypeB
};
class NodeA
{
public:
friend std::ostream& operator<<(std::ostream& o, const NodeA& node)
{
return o << "a";
}
};
class NodeB
{
public:
friend std::ostream& operator<<(std::ostream& o, const NodeB& node)
{
return o << "b";
}
};
class Parser
{
private:
Subject<NodeType> m_subject;
public:
void Parse()
{
auto a = NodeA();
auto b = NodeB();
m_subject.Notify<NodeType::TypeA, NodeA>(a);
m_subject.Notify<NodeType::TypeB, NodeB>(b);
}
void Attach(Observer<NodeA>& observer)
{
m_subject.Attach(NodeType::TypeA, observer);
}
void Attach(Observer<NodeB>& observer)
{
m_subject.Attach(NodeType::TypeB, observer);
}
};
int main()
{
auto observerA = OutputtingObserver<NodeA>();
auto observerB = OutputtingObserver<NodeB>();
auto parser = Parser();
parser.Attach(observerA);
parser.Attach(observerB);
parser.Attach(observerA);
parser.Parse();
return 1;
}
This is closer to your version. Quite unsafe and slower but slightly less typing.
Summary
Both output a\na\nb and both are something sewn together just as a minimal proof of concept, not something you should follow (especially the working with unordered_map feels quite nasty).
It's not directly what you want but I guess that you can take it from there...
I have strong feeling that there are better solutions to this so feel free to experiment.
EDIT:
Solution #3: Completely dynamic
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <iostream>
#include <typeinfo>
#include <typeindex>
template<typename TAttribute>
class Observer
{
public:
virtual void Observe(TAttribute& attribute) = 0;
virtual ~Observer() = default;
};
class Subject
{
private:
using ObserverList = std::vector<void*>;
using ObserverMap = std::unordered_map<std::type_index, ObserverList>;
ObserverMap mutable m_observers;
public:
template<typename TAttribute>
void Attach(Observer<TAttribute>& observer) const
{
auto index = std::type_index(typeid(Observer<TAttribute>));
auto itr = m_observers.find(index);
if (itr == m_observers.end())
{
m_observers.emplace(std::make_pair(index, ObserverList { &observer }));
return;
}
itr->second.push_back(&observer);
}
template<typename TAttribute>
void Detach(Observer<TAttribute>& observer) const
{
m_observers.erase(std::remove(m_observers.begin(), m_observers.end(), &observer), m_observers.end());
}
template<typename TAttribute>
void Notify(TAttribute& attribute)
{
auto itr = m_observers.find(std::type_index(typeid(Observer<TAttribute>)));
if (itr == m_observers.end())
return;
for (auto observer : itr->second)
static_cast<Observer<TAttribute>*>(observer)->Observe(attribute);
}
};
This is basically a ported C#'s version of Dictionary<Type, Object>, it uses rtti so you might get spat on by C++ hardliners...

Dynamic Object in C++?

I realize that I'll most likely get a lot of "you shouldn't do that because..." answers and they are most welcome and I'll probably totally agree with your reasoning, but I'm curious as to whether this is possible (as I envision it).
Is it possible to define a type of dynamic/generic object in C++ where I can dynamically create properties that are stored and retrieved in a key/value type of system? Example:
MyType myObject;
std::string myStr("string1");
myObject.somethingIJustMadeUp = myStr;
Note that obviously, somethingIJustMadeUp is not actually a defined member of MyType but it would be defined dynamically. Then later I could do something like:
if(myObject.somethingIJustMadeUp != NULL);
or
if(myObject["somethingIJustMadeUp"]);
Believe me, I realize just how terrible this is, but I'm still curious as to whether it's possible and if it can be done in a way that minimizes it's terrible-ness.
C++Script is what you want!
Example:
#include <cppscript>
var script_main(var args)
{
var x = object();
x["abc"] = 10;
writeln(x["abc"]);
return 0;
}
and it's a valid C++.
You can do something very similar with std::map:
std::map<std::string, std::string> myObject;
myObject["somethingIJustMadeUp"] = myStr;
Now if you want generic value types, then you can use boost::any as:
std::map<std::string, boost::any> myObject;
myObject["somethingIJustMadeUp"] = myStr;
And you can also check if a value exists or not:
if(myObject.find ("somethingIJustMadeUp") != myObject.end())
std::cout << "Exists" << std::endl;
If you use boost::any, then you can know the actual type of value it holds, by calling .type() as:
if (myObject.find("Xyz") != myObject.end())
{
if(myObject["Xyz"].type() == typeid(std::string))
{
std::string value = boost::any_cast<std::string>(myObject["Xyz"]);
std::cout <<"Stored value is string = " << value << std::endl;
}
}
This also shows how you can use boost::any_cast to get the value stored in object of boost::any type.
This can be a solution, using RTTI polymorphism
#include <map>
#include <memory>
#include <iostream>
#include <stdexcept>
namespace dynamic
{
template<class T, class E>
T& enforce(T& z, const E& e)
{ if(!z) throw e; return z; }
template<class T, class E>
const T& enforce(const T& z, const E& e)
{ if(!z) throw e; return z; }
template<class Derived>
class interface;
class aggregate;
//polymorphic uncopyable unmovable
class property
{
public:
property() :pagg() {}
property(const property&) =delete;
property& operator=(const property&) =delete;
virtual ~property() {} //just make it polymorphic
template<class Interface>
operator Interface*() const
{
if(!pagg) return 0;
return *pagg; //let the aggregate do the magic!
}
aggregate* get_aggregate() const { return pagg; }
private:
template<class Derived>
friend class interface;
friend class aggregate;
static unsigned gen_id()
{
static unsigned x=0;
return enforce(++x,std::overflow_error("too many ids"));
}
template<class T>
static unsigned id_of()
{ static unsigned z = gen_id(); return z; }
aggregate* pagg;
};
template<class Derived>
class interface: public property
{
public:
interface() {}
virtual ~interface() {}
unsigned id() const { return property::id_of<Derived>(); }
};
//sealed movable
class aggregate
{
public:
aggregate() {}
aggregate(const aggregate&) = delete;
aggregate& operator=(const aggregate&) = delete;
aggregate(aggregate&& s) :m(std::move(s.m)) {}
aggregate& operator=(aggregate&& s)
{ if(this!=&s) { m.clear(); std::swap(m, s.m); } return *this; }
template<class Interface>
aggregate& add_interface(interface<Interface>* pi)
{
m[pi->id()] = std::unique_ptr<property>(pi);
static_cast<property*>(pi)->pagg = this;
return *this;
}
template<class Inteface>
aggregate& remove_interface()
{ m.erase[property::id_of<Inteface>()]; return *this; }
void clear() { m.clear(); }
bool empty() const { return m.empty(); }
explicit operator bool() const { return empty(); }
template<class Interface>
operator Interface*() const
{
auto i = m.find(property::id_of<Interface>());
if(i==m.end()) return nullptr;
return dynamic_cast<Interface*>(i->second.get());
}
template<class Interface>
friend aggregate& operator<<(aggregate& s, interface<Interface>* pi)
{ return s.add_interface(pi); }
private:
typedef std::map<unsigned, std::unique_ptr<property> > map_t;
map_t m;
};
}
/// this is a sample on how it can workout
class interface_A: public dynamic::interface<interface_A>
{
public:
virtual void methodA1() =0;
virtual void methodA2() =0;
};
class impl_A1: public interface_A
{
public:
impl_A1() { std::cout<<"creating impl_A1["<<this<<"]"<<std::endl; }
virtual ~impl_A1() { std::cout<<"deleting impl_A1["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_A2: public interface_A
{
public:
impl_A2() { std::cout<<"creating impl_A2["<<this<<"]"<<std::endl; }
virtual ~impl_A2() { std::cout<<"deleting impl_A2["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
};
class interface_B: public dynamic::interface<interface_B>
{
public:
virtual void methodB1() =0;
virtual void methodB2() =0;
};
class impl_B1: public interface_B
{
public:
impl_B1() { std::cout<<"creating impl_B1["<<this<<"]"<<std::endl; }
virtual ~impl_B1() { std::cout<<"deleting impl_B1["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_B2: public interface_B
{
public:
impl_B2() { std::cout<<"creating impl_B2["<<this<<"]"<<std::endl; }
virtual ~impl_B2() { std::cout<<"deleting impl_B2["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
};
int main()
{
dynamic::aggregate agg1;
agg1 << new impl_A1 << new impl_B1;
dynamic::aggregate agg2;
agg2 << new impl_A2 << new impl_B2;
interface_A* pa = 0;
interface_B* pb = 0;
pa = agg1; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
agg2 = std::move(agg1);
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
return 0;
}
tested with MINGW4.6 on WinXPsp3
Yes it is terrible. :D
It had been done numerous times to different extents and success levels.
QT has Qobject from which everything related to them decends.
MFC has CObject from which eveything decends as does C++.net
I don't know if there is a way to make it less bad, I guess if you avoid multiple inheritance like the plague (which is otherwise a useful language feature) and reimplement the stdlib it would be better. But really if that is what you are after you are probably using the wrong language for the task.
Java and C# are much better suited to this style of programming.
#note if I have read your question wrong just delete this answer.
Check out Dynamic C++

one to one association

What is the best way to represent one-to-one object association in C++? It should be as automatic and transparent as possible meaning, that when one end is set or reset, the other end will be updated. Probably a pointer-like interface would be ideal:
template<typename AssociatedType>
class OneToOne{
void Associate(AssociatedType &);
AssociatedType &operator* ();
AssociatedType *operator->();
}
Is there any better way to do it or is there any complete implementation?
EDIT:
Desired behavior:
struct A{
void Associate(struct B &);
B &GetAssociated();
};
struct B{
void Associate(A &);
A &GetAssociated();
};
A a, a2;
B b;
a.Associate(b);
// now b.GetAssociated() should return reference to a
b.Associate(a2);
// now b.GetAssociated() should return reference to a2 and
// a2.GetAssociated() should return reference to b
// a.GetAssociated() should signal an error
Untested, but you could use a simple decorator
template <typename A1, typename A2>
class Association
{
public:
void associate(A2& ref)
{
if (_ref && &(*_ref) == &ref) return; // no need to do anything
// update the references
if (_ref) _ref->reset_association();
// save this side
_ref = ref;
ref.associate(static_cast<A1&>(*this));
}
void reset_association() { _ref = boost::none_t(); }
boost::optional<A2&> get_association() { return _ref; }
private:
boost::optional<A2&> _ref;
};
now:
struct B;
struct A : public Association<A, B> {
};
struct B : public Association<B, A> {
};
now these operations should be handled correctly.
A a, a2;
B b;
a.associate(b);
b.associate(a2);
NOTES: I use boost::optional to hold a reference rather than pointer, there is nothing stopping you from using pointers directly. The construct you are after I don't think exists by default in C++, which is why you need something like the above to get it to work...
Here is one class that can represent a bi-directional one-to-one relation:
template <class A, class B>
class OneToOne {
OneToOne<A,B>* a;
OneToOne<A,B>* b;
protected:
OneToOne(A* self) : a(self), b(0) {}
OneToOne(B* self) : a(0), b(self) {}
public:
void associateWith(OneToOne<A,B>& other) {
breakAssociation();
other.breakAssociation();
if (a == this) {
if (b != &other) {
breakAssociation();
other.associateWith(*this);
b = &other;
}
}
else if (b == this) {
if (a != &other) {
breakAssociation();
other.associateWith(*this);
a = &other;
}
}
}
A* getAssociatedObject(B* self) { return static_cast<A*>(a); }
B* getAssociatedObject(A* self) { return static_cast<B*>(b); }
void breakAssociation() {
if (a == this) {
if (b != 0) {
OneToOne<A,B>* temp = b;
b = 0;
temp->breakAssociation();
}
}
else if (b == this) {
if (a != 0) {
OneToOne<A,B>* temp = a;
a = 0;
temp->breakAssociation();
}
}
}
private:
OneToOne(const OneToOne&); // =delete;
OneToOne& operator=(const OneToOne&); // =delete;
};
Perhaps check out boost::bimap, a bidirectional maps library for C++.