здесь возникает проблема, когда я читаю sigslot с открытым исходным кодом (http://sigslot.sourceforge.net), существует класс с именем _opaque_connection , используемый для сохранения указателя на функцию класса с указателем на объект класса , но я не понимаю, почему он использует union_caster для преобразования и сохранения указателя функции вместо непосредственного его сохранения
вот код
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.");
std::memcpy(pmethod, &pm, sizeof(pm_t));
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 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 back 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...);
}
};
мы можно увидеть в _opaque_connection (DestT * pd, void (DestT :: * pm) (Args ...)) он использует заклинатель для преобразования указателя функции и присвоения ему pemit , затем преобразуйте его обратно в void emit (Args ... args) ; почему бы не сделать тип pemit как void ( em_t) (const _opaque_connection self, Args .. .); , поэтому не требуется никаких преобразований