Portál AbcLinuxu, 31. října 2025 11:25
A *o na *functor, možná to jen nechápu...
             10.2.2017 18:26
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        10.2.2017 18:26
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        struct { size_t a; size_t b; };
Nejspíš by se i našel způsob, jak během compile-time zjistit, jestli ten member func pointer není větší...
            operator (), protože tam se to castuje na jiný typ, než který byl uložený, a každý může mít jinak velké member pointery.
            #ifndef NDEBUG ... #endif)
             11.2.2017 16:00
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        11.2.2017 16:00
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
         10.2.2017 17:31
Josef Kufner             | skóre: 70
        10.2.2017 17:31
Josef Kufner             | skóre: 70
            
            
         10.2.2017 18:26
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        10.2.2017 18:26
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        at je hází úmyslně, neházející verze je operator [].
GCC má debug verzi STL, která asserty obsahuje.
            typeid(void(Ts...)) nebo neco podobneho.
            
template <typename ReturnT, typename... ParamTs>
class Callback
{
protected:
    struct Iface
    {
        virtual ~Iface() {}
        virtual ReturnT operator ()(ParamTs... params) = 0;
    };
    template <typename Type>
    struct Impl
        : public Iface
    {
        using Func = ReturnT (Type::*)(ParamTs...);
        Impl(Type &obj, Func func)
            : obj(obj)
            , func(func)
        {}
        virtual ~Impl() {}
        virtual ReturnT operator ()(ParamTs... params)
        {
            return std::forward<ReturnT>(obj.*func(std::forward<ParamTs...>(params)));
        }
        Type &obj;
        Func func;
    };
    Iface& iface()
    {
        return *reinterpret_cast<Iface*>(buf);
    }
    size_t buf[4];
public:
    template <typename Type>
    Callback(Type &obj,
             typename Impl<Type>::Func func)
    {
        // Místo static_assert lze upravit, aby to použilo new
        static_assert(sizeof(Impl<Type>) <= sizeof(buf), "Buffer not large enough to capture callback");
        new (buf) Impl<Type>(obj, func);
    }
    ~Callback()
    {
        iface().~Iface();
    }
    ReturnT operator ()(ParamTs... params)
    {
        return std::forward<ReturnT>(iface()(std::forward<ParamTs...>(params)));
    }
};
Callback callback(t, &Type::getValueForInput);
int value = callback(input);
            std::forward na návratové hodnoty je zbytečný, navíc nebude fungovat s void.
virtual ReturnT operator ()(ParamTs... params) a virtual ~Impl() v Impl by bylo lepší označit override.
            Callback templatová třída, pak se rovnou může použít std::function, ne?
            operator ()) by šlo zabalit přes reinterpret_cast, protože není polymorfní (takže je to jen pointer na funkci, kde první parametr je this), ale nebude to ověřovat typy parametrů.
Ten reinterpret_cast v původní implementaci nebude fungovat, pokud bude castovat z polymorfní třídy na nepolymorfní či obráceně, a nejspíš ani pokud bude mezi různými stromy polymorfních tříd, protože u virtuálních metod je to typicky implementováno jako index do vtable, nikoliv pointer.
             11.2.2017 15:53
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        11.2.2017 15:53
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
         13.2.2017 23:54
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        13.2.2017 23:54
vlastikroot             | skóre: 24
             | blog: vlastikovo
             | Milevsko
        
class functor
{
protected:
    struct iface { virtual ~iface(){}; };
    template <typename... Ts> struct args : public iface
    {
        virtual void call(Ts...) = 0;
    };
    template <typename A, typename... Ts> struct impl : public args<Ts...>
    {
        A* obj;
        void (A::*func)(Ts...);
        impl(A* o, void (A::*f)(Ts...)) : obj(o), func(f) {}
        void call(Ts... args)
        {
            (obj->*func)(args...);
        }
    };
    size_t i[4];
public:
    template<typename A, typename... Ts> functor(A* o, void (A::*f)(Ts...))
    {
        static_assert(sizeof(impl<A, Ts...>) <= sizeof(i), "Buffer not large enough to capture callback");
        new (i) impl<A, Ts...>(o,f);
    }
    template<typename... Ts> void operator()(Ts... params)
    {
        args<Ts...> *a = dynamic_cast<args<Ts...>*>(reinterpret_cast<iface*>(i));
        if(a) a->call(params...);
        else qDebug() << "bad parameters";
    }
};
            
        Tiskni
            
                Sdílej:
                 
                 
                 
                 
                 
                 
            
    
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.