one to one association - c++

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++.

Related

Reducing the number of overloaded functions and constructors

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);
}

Change Operation at runtime in C++

I have a small problem at hand. Suppose there is a if condition with only 2 operands but I want to make the operation dynamic.
void somFunc()
{
if(a && b) /*1*/
{
}
else if(a1 && b1) /*2*/
{
}
else if(a || b) /*3*/
{
}
else if(a1 || b1) /*4*/
}
Basically, 1 and 3 exactly has same parameters with different operation,Similarly for 2 and 4. I want to reduce these 4 operations to 2.
I want to know if there is a way I can make oper dynamic. Consider we only have 2 operations && and ||Can I use templates in any way ?
If someone wants to know why I need this is, there are n if conditions inside a big if/else. If I somehow achieve this, I reduce the conditions by half.
Not sure if this is what you are asking for, but you can write something like this:
enum OPERATION { AND, OR };
bool operation(bool a, bool b,OPERATION op) {
if (op == AND) return a && b;
return a || b;
}
void somFunc(OPERATION op)
{
if(operation(a,b,op))
{
}
}
Or as suggested in a comment, make the operation to be performed a parameter of the function, like so
template <OPERATION>
void somFunc(OPERATION op)
{
if(op(a,b))
{
}
}
and call it like this
somFunc( [](bool a, bool b) { return a && b; });
somFunc( [](bool a, bool b) { return a || b; });
You can use pointers to funtions.
#include <iostream>
#include <functional>
bool oper1(bool a, bool b) {
return a || b;
}
bool oper2(bool a, bool b) {
return a && b;
}
int main() {
bool a = true, b = false;
auto oper = oper1;
if (oper(a, b)) {
std::cout << "OR\n";
}
oper = oper2;
if (oper(a, b)) {
std::cout << "AND\n";
}
}
First you define all your conditions and later you can switch the condition by setting the variable.
You can also use inheritance and functors:
#include <iostream>
#include <functional>
#include <memory>
class Operator {
public:
virtual bool eval(bool a, bool b) = 0;
};
class OrOperator : public Operator {
public:
bool eval(bool a, bool b) {
return a || b;
}
};
class AndOperator : public Operator {
public:
bool eval(bool a, bool b) {
return a && b;
}
};
class VariableOperator : public Operator {
public:
VariableOperator(bool val) : val(val) {}
bool eval(bool a, bool b) {
return val;
}
private:
bool val;
};
int main() {
bool a = true, b = false;
std::unique_ptr<Operator> oper(new OrOperator);
if (oper->eval(a, b)) {
std::cout << "OR\n";
}
oper.reset(new AndOperator);
if (oper->eval(a, b)) {
std::cout << "AND\n";
}
oper.reset(new VariableOperator(true));
if (oper->eval(a, b)) {
std::cout << "VARIABLE\n";
}
}
You might be looking for something like this:
void somFunc()
{
std::vector< std::function< bool(bool, bool) > > operators = {
[](bool a, bool b){ return a && b; },
[](bool a, bool b){ return a || b; }
};
for ( auto& op : operators )
{
if ( op( a, b ) )
{
}
else if ( op( a1, b1 ) )
{
}
}
}
You can add more operators or change the parameter types easily enough.
You can do this with CRTP too:
#include <iostream>
#include <string>
#include <memory>
template<class T>
class Operation
{
public:
bool eval(bool a, bool b)
{
return this->impl().eval(a,b);
}
private:
T& impl() { return static_cast<T&>(*this); }
};
class AndOperation : public Operation<AndOperation>
{
public:
bool eval(bool a, bool b)
{
return a && b;
}
};
class OrOperation : public Operation<OrOperation>
{
public:
bool eval(bool a, bool b)
{
return a || b;
}
};
int main()
{
AndOperation andOp;
auto anonOp = std::make_unique<OrOperation>();
std::cout << andOp.eval(true, true) << std::endl;
std::cout << anonOp->eval(false,false);
}
see live example here
What are the advantages of CRTP over virtual inheritance?
CRTP is a case of static polymorphism. Here's some references:
Compile time vs run time polymorphism in C++ advantages/disadvantages
What is the motivation behind static polymorphism in C++?
C++: How is this technique of compile-time polymorphism called and what are the pros and cons?
The cost of dynamic (virtual calls) vs. static (CRTP) dispatch in C++
It is possible to make somFunc() a template, and accept any function that accepts two arguments and returns a value that can be tested with if.
#include <functional> // for binary operations in std
template<class Operation> void somfunc(Operation oper)
{
if (oper(a,b))
{
// whatever
}
}
int main()
{
somFunc(std::logical_and<int>());
somFunc(std::logical_or<int>());
somFunc(std::plus<int>()); // addition
// pass a lambda
somFunc([](int a, int b) -> int {return a + b;}); // lambda form of addition
}
In the above, I've assumed the variables a and b (which have been used in the question, but types unspecified) are of type int.

"Cannot convert from 'A' to 'B&'

I'm building an Entity-Component system using template metaprogramming. I keep getting either Cannot convert from [base type] to [type user requested]& or Cannot convert NullComponent to [type user requested]& errors:
class Entity {
public:
Entity() = default;
~Entity() = default;
template<typename C, typename... Args>
void AddComponent(Args&&... args);
template<typename C>
C& GetComponent();
protected:
private:
//...add/get helper methods here...
unsigned int _id;
std::vector<std::unique_ptr<IComponent>> _components;
};
template<typename C>
C& Entity::GetComponent() {
for(auto c : _components) {
if(std::is_base_of<a2de::IComponent&, C&>().value && std::is_same<decltype(c), C&>().value) {
return *c; //<-- error here
}
}
return NullComponent(); //<-- and here
}
EDIT
These options seem to work for now.
template<typename C>
const C& Entity::GetComponent() const {
for(auto& uc : _components) {
auto* c = dynamic_cast<C*>(uc.get());
if(c && std::is_base_of<a2de::IComponent&, C&>().value && std::is_same<decltype(c), C&>().value) {
return *c;
}
}
throw std::runtime_error(std::string("Component not available."));
}
OR
class Entity {
public:
//same as before...
protected:
private:
//same as before...
a2de::NullComponent _null_component;
};
template<typename C>
const C& Entity::GetComponent() const {
for(auto& uc : _components) {
auto* c = dynamic_cast<C*>(uc.get());
if(c && std::is_base_of<a2de::IComponent&, C&>().value && std::is_same<decltype(c), C&>().value) {
return *c;
}
}
return _null_component;
}
At least three things:
In GetComponent() you iterate over unique_ptr elements and compare their type (always std::unique_ptr<IComponent>) with something else in the std::is_same. You probably don't want that.
You are returning a reference to a temporary in the final return, it seems.
return *c needs a dynamic_cast unless C == IComponent.
EDIT
Also:
std::is_base_of makes no sense with references. Even with class NullComponent : IComponent {};, you would still get std::is_base_of<IComponent&, NullComponent&>::value == false.
And you do not check for nullptr
In the end, it seems to me that you should replace your for loop with
for(auto& component : _components) {
auto* c = dynamic_cast<C*>(component.get());
if (c)
{
return *c;
}
}
At a high level, from what I can figure out, the return type cannot be used to define the template type. The parameter list can be used to define the template type.
So, for example, this might work -
template<typename C>
void Entity::GetComponent(C *obj) {
for(auto c : _components) {
if(std::is_base_of<a2de::IComponent&, C&>().value && std::is_same<decltype(c), C&>().value) {
obj = c; //<-- error here
return;
}
}
obj = NULL;
return; //<-- and here
}
Hope this helps.

Is casting non-polymorphic structs with common base and layout valid C++?

Is the following code valid C++? Otherwise, is there a valid way to simultaneously interpret memory as values of different type?
#include <cstdio>
struct Base { int payload; };
struct D1 : Base { void operator()(){ printf("D1: %d\n", payload);} };
struct D2 : Base { void operator()(){ printf("D2: %d\n", payload);} };
int main()
{
D1 d1;
D2& d2 = static_cast<D2&>(static_cast<Base&>(d1));
d1();
d2();
d2.payload = 3;
d1();
d2();
}
In response to #NickoPo: My use case is basically what follows. Imagine that IntBase is not necessarily cheap to copy, that there are many complex algorithms, some of which profit from numbers being prime vs. odd, and others don't:
#include <cassert>
#include <cstdio>
bool is_odd(int value) { return 0 != value % 2; }
bool is_small_prime(int value) { return 2 == value || 3 == value || 5 == value || 7 == value; }
class IntBase
{
public:
explicit IntBase(int value) : m_value(value) {}
int value() const { return m_value; }
protected:
int m_value;
};
class OddInt : public IntBase
{
public:
explicit OddInt(int value) : IntBase(value) { assert(is_odd(m_value)); }
};
class SmallPrimeInt : public IntBase
{
public:
explicit SmallPrimeInt(int value) : IntBase(value) { assert(is_small_prime(m_value)); }
};
bool is_constrainable_to_odd_int(IntBase const& x)
{
return is_odd(x.value());
}
OddInt const& constrain_to_odd_int(IntBase const& x)
{
assert(is_odd(x.value()));
return static_cast<OddInt const&>(x);
}
bool is_constrainable_to_small_prime_int(IntBase const& x)
{
return is_small_prime(x.value());
}
SmallPrimeInt const& constrain_to_small_prime_int(IntBase const& x)
{
assert(is_small_prime(x.value()));
return static_cast<SmallPrimeInt const&>(x);
}
void algorithm(IntBase const&)
{
printf("algoritm(IntBase const&)\n");
}
void algorithm(OddInt const&)
{
printf("algoritm(OddInt const&)\n");
}
void algorithm(SmallPrimeInt const&)
{
printf("algoritm(SmallPrimeInt const&)\n");
}
void test(IntBase const& x)
{
if (is_constrainable_to_small_prime_int(x))
{
algorithm(constrain_to_small_prime_int(x));
}
else if (is_constrainable_to_odd_int(x))
{
algorithm(constrain_to_odd_int(x));
}
else
{
algorithm(x);
}
}
void test(OddInt const& x)
{
if (is_constrainable_to_small_prime_int(x))
{
algorithm(constrain_to_small_prime_int(x));
}
else
{
algorithm(constrain_to_odd_int(x));
}
}
int main()
{
IntBase x(0);
OddInt y(1);
OddInt z(7);
test(x); // algoritm(IntBase const&)
test(y); // algoritm(OddInt const&)
test(z); // algoritm(SmallPrimeInt const&)
}
Related:
Can I legally reinterpret_cast between layout-compatible standard-layout types?
Answer to Safety of casting between pointers of two identical classes?
If you're going to cast while using similar interfaces while using type as a guarantee, I'd recommend that you just wrap the inner data with your new object type and then provide access to the inner data in order to transfer it from one type to another. There's no point in doing static casting or reinterpret casting if you're not going to do it safely.
Here's an example:
http://coliru.stacked-crooked.com/a/40d5efeff22fcdcd
#include <iostream>
//Base data structure to encapsulate only data.
struct data {
data(int i) : i(i) {}
int i;
};
//Wrapper around our data structure, with interfaces to access
//the values and the data; implement your own constructor to
//gate the value
class PrimeInt {
public:
PrimeInt(const int i)
: d(i) {}
PrimeInt(const data& other)
: d(other) {}
PrimeInt(data&& other)
: d(std::move(other)) {}
PrimeInt& operator=(const PrimeInt&) = default;
PrimeInt& operator=(PrimeInt&&) = default;
int get() {return d.i;};
operator data() {return d;};
private:
data d;
};
//Wrapper around our data structure, with interfaces to access
//the values and the data; implement your own constructor to
//gate the value
class OddInt {
public:
OddInt(const int i)
: d(i) {}
OddInt(const data& other)
: d(other) {}
OddInt(data&& other)
: d(std::move(other)) {}
OddInt& operator=(const OddInt&) = default;
OddInt& operator=(OddInt&&) = default;
int get() {return d.i;};
operator data() {return d;};
private:
data d;
};
//Notice that we can now implicitly cast from one type to another.
int main() {
PrimeInt pi(10);
std::cout << pi.get() << std::endl;
OddInt oi(pi);
std::cout << oi.get() << std::endl;
return 0;
}
If your objects are not cheap to copy, you are probably passing pointers or references everywhere. You can wrap pointers to your common base in different class types and pass them by value. That is, instead of this (pseudocode)
class B
class D1 : B { ... }
class D2 : B { ... }
D1* d1; D2* d2;
you have
class Bimpl
class B { Bimpl* bimpl; }
class D1 : B { ... }
class D2 : B { ... }
D1 d1; D2 d2;
Here you never do any built-in cast. If you want to convert D1 to D2, you write your own conversion function.

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++