here comes a trouble to me while I am reading a open source sigslot(http://sigslot.sourceforge.net), there a class named _opaque_connection used to save Class function pointer with Class object pointer , but I don't understand why does it use a union_caster to convert and save function pointer instead of save it directly
here is the code
class _opaque_connection {
private:
typedef void (*emit_t)(const _opaque_connection*);
//function pointer convertor
template <typename FromT, typename ToT>
union union_caster {
FromT from;
ToT to;
};
emit_t pemit;
has_slots_interface* pdest;
unsigned char pmethod[16];
public:
template <typename DestT, typename... Args>
_opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdest(pd) {
typedef void (DestT::*pm_t)(Args...);
static_assert(sizeof(pm_t) <= sizeof(pmethod),
"Size of slot function pointer too large.");
typedef void (*em_t)(const _opaque_connection* self, Args...);
union_caster<em_t, emit_t> caster2;
caster2.from = &_opaque_connection::emitter<DestT, Args...>; //why here need to use a caster to convert?
pemit = caster2.to; //convert it and save function pointer
}
has_slots_interface* getdest() const { return pdest; }
_opaque_connection duplicate(has_slots_interface* newtarget) const {
_opaque_connection res = *this;
res.pdest = newtarget;
return res;
}
template <typename... Args>
void emit(Args... args) const {
typedef void (*em_t)(const _opaque_connection*, Args...);
union_caster<emit_t, em_t> caster; //then convert it back
caster.from = pemit;
(caster.to)(this, args...); //convert it and use function pointer
}
private:
template <typename DestT, typename... Args>
static void emitter(const _opaque_connection* self, Args... args) {
typedef void (DestT::*pm_t)(Args...);
pm_t pm;
std::memcpy(&pm, self->pmethod, sizeof(pm_t));
(static_cast<DestT*>(self->pdest)->*(pm))(args...);
}
};
we can see in _opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) it uses a caster to convert function pointer and assign it to pemit, then connvert it back in void emit(Args... args); why don't make pemit's type as void (em_t)(const _opaque_connection self, Args...);, so it doesn't need any convertions
Aucun commentaire:
Enregistrer un commentaire