#ifndef SYG_connection_HPP
#define SYG_connection_HPP
#include <list>
namespace syg
{
template <typename Tret>
class connection_base
{
public:
virtual Tret call() const = 0;
virtual connection_base<Tret>* clone() const = 0;
virtual ~connection_base() {}
};
template <typename Tret, typename Targ0>
class connection_base1
{
public:
virtual Tret call(Targ0) const = 0;
virtual connection_base1<Tret, Targ0>* clone() const = 0;
virtual ~connection_base1() {}
};
template <typename Tret>
class connection_func : public connection_base<Tret>
{
public:
typedef Tret (*FuncPtr)();
connection_func(FuncPtr ptr):
_func(ptr)
{}
Tret call() const
{
return _func();
}
connection_base<Tret>* clone() const
{
return new connection_func<Tret>(*this);
}
private:
FuncPtr _func;
};
template <typename Tret, typename Targ0>
class connection_func1 : public connection_base1<Tret, Targ0>
{
public:
typedef Tret (*FuncPtr)(Targ0);
connection_func1(FuncPtr ptr):
_func(ptr)
{}
Tret call(Targ0 arg0) const
{
return _func(arg0);
}
connection_base1<Tret, Targ0>* clone() const
{
return new connection_func1<Tret, Targ0>(*this);
}
private:
FuncPtr _func;
};
template <typename Tobj, typename Tret>
class connection_meth : public connection_base<Tret>
{
public:
typedef Tobj TypeObj;
typedef Tret (Tobj::*FuncPtr)();
connection_meth(TypeObj& obj, FuncPtr ptr):
_obj(obj),
_meth(ptr)
{}
Tret call() const
{
return (_obj.*_meth)();
}
connection_base<Tret>* clone() const
{
return new connection_meth<Tobj, Tret>(*this);
}
private:
Tobj& _obj;
FuncPtr _meth;
};
template <typename Tobj, typename Tret, typename Targ0>
class connection_meth1 : public connection_base1<Tret, Targ0>
{
public:
typedef Tobj TypeObj;
typedef Tret (Tobj::*FuncPtr)(Targ0);
connection_meth1(TypeObj& obj, FuncPtr ptr):
_obj(obj),
_meth(ptr)
{}
Tret call(Targ0 arg0) const
{
return (_obj.*_meth)(arg0);
}
connection_base1<Tret, Targ0>* clone() const
{
return new connection_meth1<Tobj, Tret, Targ0>(*this);
}
private:
Tobj& _obj;
FuncPtr _meth;
};
template <typename Tret>
class slot;
template <typename Tret, typename Targ0>
class slot1;
template <typename Tret>
slot<Tret> ptr_fun(Tret (*fun)());
template <typename Tobj, typename Tret>
slot<Tret> mem_fun(Tobj& obj, Tret (Tobj::*fun)());
template <typename Tret, typename Targ0>
slot1<Tret, Targ0> ptr_fun(Tret (*fun)(Targ0));
template <typename Tobj, typename Tret, typename Targ0>
slot1<Tret, Targ0> mem_fun(Tobj& obj, Tret (Tobj::*fun)(Targ0));
template <typename Tret>
class slot
{
public:
slot():
_conn(0)
{}
slot(const slot<Tret>& s)
{
*this = s;
}
~slot()
{
delete _conn;
}
slot& operator=(const slot<Tret>& s)
{
if (s._conn)
_conn = s._conn->clone();
else
_conn = 0;
return *this;
}
Tret call() const
{
return _conn->call();
}
Tret operator()() const
{
return call();
}
operator bool() const
{
return _conn;
}
private:
connection_base<Tret>* _conn;
slot(const connection_base<Tret>& conn):
_conn(conn.clone())
{}
friend slot<Tret> ptr_fun<Tret>(Tret (*fun)());
template <typename Tobj2, typename Tret2>
friend slot<Tret2> mem_fun(Tobj2& obj, Tret2 (Tobj2::*fun)());
};
template <typename Tret, typename Targ0>
class slot1
{
public:
typedef slot1<Tret, Targ0> SlotType;
slot1():
_conn(0)
{}
slot1(const SlotType& s)
{
*this = s;
}
~slot1()
{
delete _conn;
}
slot1& operator=(const SlotType& s)
{
if (s._conn)
_conn = s._conn->clone();
else
_conn = 0;
return *this;
}
Tret call(Targ0 arg0) const
{
return _conn->call(arg0);
}
Tret operator()(Targ0 arg0) const
{
return call(arg0);
}
operator bool() const
{
return _conn;
}
private:
typedef connection_base1<Tret, Targ0> Connection;
Connection* _conn;
slot1(const Connection& conn):
_conn(conn.clone())
{}
friend SlotType ptr_fun<Tret, Targ0>(Tret (*fun)(Targ0));
template <typename Tobj2, typename Tret2, typename Targ02>
friend slot1<Tret2, Targ02> mem_fun(Tobj2& obj,
Tret2 (Tobj2::*fun)(Targ02));
};
template <typename Tret>
inline slot<Tret> ptr_fun(Tret (*fun)())
{
return slot<Tret>(connection_func<Tret>(fun));
}
template <typename Tobj, typename Tret>
inline slot<Tret> mem_fun(Tobj& obj, Tret (Tobj::*fun)())
{
return slot<Tret>(connection_meth<Tobj, Tret>(obj, fun));
}
template <typename Tret, typename Targ0>
inline slot1<Tret, Targ0> ptr_fun(Tret (*fun)(Targ0))
{
return slot1<Tret, Targ0>(connection_func1<Tret, Targ0>(fun));
}
template <typename Tobj, typename Tret, typename Targ0>
inline slot1<Tret, Targ0> mem_fun(Tobj& obj, Tret (Tobj::*fun)(Targ0))
{
return slot1<Tret, Targ0>(connection_meth1<Tobj, Tret, Targ0>(obj, fun));
}
}
#endif