какова цель удара по коду в opaque_connection siglot.h - PullRequest
0 голосов
/ 11 января 2020

здесь возникает проблема, когда я читаю 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 .. .); , поэтому не требуется никаких преобразований

...