Saturday, May 04, 2013

And here is the same thing using variadic template arguments, a new feature of C++11:



template class base_t
{
public:
virtual R operator()(Args... p) { return R(); }
};

template class stub_t : public base_t
{
T* _obj;
union
{
R (T::*_ptr)(Args...);
R (T::*_ptr_c)(Args...) const;
};

public:
stub_t(T* obj, R (T::*ptr)(Args...))
: _obj(obj), _ptr(ptr)
{
}
stub_t(T* obj, R (T::*ptr)(Args...) const)
: _obj(obj), _ptr_c(ptr)
{
}
R operator()(Args... p)
{
return (_obj->*_ptr)(p...);
}
};

template class signal_t
{
R(*_ptr)(Args...);
base_t* _stub;

public:
signal_t() : _ptr(nullptr), _stub(nullptr)
{
}
void connect(R(*ptr)(Args... args))
{
_ptr = ptr;
};

template void connect(T& obj, R(T::*ptr)(Args...))
{
_stub = new stub_t(&obj, ptr);
}
template void connect(T* obj, R(T::*ptr)(Args...) )
{
_stub = new stub_t(obj, ptr);
}
template void connect(T& obj, R(T::*ptr)(Args...) const)
{
_stub = new stub_t(&obj, ptr);
}
template void connect(T* obj, R(T::*ptr)(Args...) const)
{
_stub = new stub_t(obj, ptr);
}

R operator()(Args... p)
{
if(_ptr)
return _ptr(p...);
else if(_stub)
return (*_stub)(p...);
else
return R();
}
};


Saves a few hundred lines of code, as well as reducing the number of places bugs can crop up.

Friday, May 03, 2013

Here is some signal/slot stuff that I've recently put together:


template class base
{
public:
virtual R call(const A1& arg1 = A1(), const A2& arg2 = A2(), const A3& arg3 = A3(), const A4& arg4 = A4())
{ return (R)(arg1, arg2, arg3, arg4); }
};

template class base
{
public:
virtual R call() { return R(); }
};

template class base
{
public:
virtual R call(const A1& arg1 = A1()) { return R(); }
};

template class base
{
public:
virtual R call(const A1& arg1 = A1(), const A2& arg2 = A2()) { return R(); }
};

template class base
{
public:
virtual R call(const A1& arg1 = A1(), const A2& arg2 = A2(), const A3& arg3 = A3()) { return R(); }
};



template 
class stub : public base
{
public:
stub(T& obj, R (T::*ptr)(A1, A2, A3, A4)) : _obj(obj), _ptr(ptr) { }
R call(const A1& arg1 = A1(), const A2& arg2 = A2(), const A3& arg3 = A3(), const A4& arg4 = A4())
{
return (_obj.*_ptr)(arg1, arg2, arg3, arg4);
}
private:
T& _obj;
R (T::*_ptr)(A1, A2, A3, A4);
};


template class stub : public base
{
public:
stub(T& obj, R (T::*ptr)()) : _obj(obj), _ptr(ptr) { }
R call()
{
return (_obj.*_ptr)();
}
private:
T& _obj;
R (T::*_ptr)();
};

template class stub : public base
{
public:
stub(T& obj, R (T::*ptr)(A1)) : _obj(obj), _ptr(ptr) { }
R call(const A1& arg1 = A1())
{
return (_obj.*_ptr)(arg1);
}
private:
T& _obj;
R (T::*_ptr)(A1);
};

template class stub : public base
{
public:
stub(T& obj, R (T::*ptr)(A1, A2)) : _obj(obj), _ptr(ptr) { }
R call(const A1& arg1 = A1(), const A2& arg2 = A2())
{
return (_obj.*_ptr)(arg1, arg2);
}
private:
T& _obj;
R (T::*_ptr)(A1, A2);
};

template class stub : public base
{
public:
stub(T& obj, R (T::*ptr)(A1, A2, A3)) : _obj(obj), _ptr(ptr) { }
R call(const A1& arg1 = A1(), const A2& arg2 = A2(), const A3& arg3 = A3())
{
return (_obj.*_ptr)(arg1, arg2, arg3);
}
private:
T& _obj;
R (T::*_ptr)(A1, A2, A3);
};


template class signal_t
{
public:
signal_t() : _ptr(0), _stub(0) { }
template void connect(T1& object, R (T1::*slot)(A1, A2, A3, A4))
{
_stub = new stub(object, slot);
}
template void connect(T1& object, R (T1::*slot)(A1, A2, A3, A4) const)
{
_stub = new stub(object, slot);
}
void connect(R (*function)(A1, A2, A3, A4)) { _ptr = function; }
R operator()(const A1& arg1 = A1(), const A2& arg2 = A2(), const A3& arg3 = A3(), const A4& arg4 = A4()) 
{
if(_ptr)
return _ptr(arg1, arg2, arg3, arg4);
else if(_stub)
return _stub->call(arg1, arg2, arg3, arg4);
else
return R();
}
private:
R (*_ptr)(A1, A2, A3, A4);
base* _stub;
};

 template class signal_t
{
public:
signal_t() : _ptr(0), _stub(0) { }
template void connect(T1& object, R (T1::*slot)())
{
_stub = new stub(object, slot);
}
template void connect(T1& object, R (T1::*slot)() const)
{
_stub = new stub(object, slot);
}
void connect(R (*function)()) { _ptr = function; }
R operator()() 
{
if(_ptr)
return _ptr();
else if(_stub)
return _stub->call();
else
return R();
}
private:
R (*_ptr)();
base* _stub;
};

 template class signal_t
{
public:
signal_t() : _ptr(0), _stub(0) { }
template void connect(T1& object, R (T1::*slot)(A1))
{
_stub = new stub(object, slot);
}
template void connect(T1& object, R (T1::*slot)(A1) const)
{
_stub = new stub(object, slot);
}
void connect(R (*function)(A1)) { _ptr = function; }
R operator()(const A1& arg1 = A1()) 
{
if(_ptr)
return _ptr(arg1);
else if(_stub)
return _stub->call(arg1);
else
return R();
}
private:
R (*_ptr)(A1);
base* _stub;
};

template class signal_t
{
public:
signal_t() : _ptr(0), _stub(0) { }
template void connect(T1& object, R (T1::*slot)(A1, A2))
{
_stub = new stub(object, slot);
}
template void connect(T1& object, R (T1::*slot)(A1, A2) const)
{
_stub = new stub(object, slot);
}
void connect(R (*function)(A1, A2)) { _ptr = function; }
R operator()(const A1& arg1 = A1(), const A2& arg2 = A2()) 
{
if(_ptr)
return _ptr(arg1, arg2);
else if(_stub)
return _stub->call(arg1, arg2);
else
return R();
}
private:
R (*_ptr)(A1, A2);
base* _stub;
};

template class signal_t
{
public:
signal_t() : _ptr(0), _stub(0) { }
template void connect(T1& object, R (T1::*slot)(A1, A2, A3))
{
_stub = new stub(object, slot);
}
template void connect(T1& object, R (T1::*slot)(A1, A2, A3) const)
{
_stub = new stub(object, slot);
}
void connect(R (*function)(A1, A2, A3)) { _ptr = function; }
R operator()(const A1& arg1 = A1(), const A2& arg2 = A2(), const A3& arg3 = A3()) 
{
if(_ptr)
return _ptr(arg1, arg2, arg3);
else if(_stub)
return _stub->call(arg1, arg2, arg3);
else
return R();
}
private:
R (*_ptr)(A1, A2, A3);
base* _stub;
};


Not sure exactly why it works but it seems to.