Информация об изменениях

Сообщение Re[5]: Связать лямбду от 12.02.2018 20:49

Изменено 12.02.2018 20:50 Alexander G

Re[5]: Связать лямбду
Здравствуйте, Marty, Вы писали:

M>Кучи нет. Кстати


Ого. Ну как-то так можно, раз new запрещён, остаётся фиксированный буфер в себе:

template<std::size_t BufferSize, class R, class... Args>
class LambdaStorage
{
public:
    template<class F>
    LambdaStorage(F f)
    {
        new (data) F(f);
        call = CallImpl<F>;
        copy = CopyImpl<F>;
        del  = DelImpl<F>;        
    }

    LambdaStorage()
    {
        call = nullptr;
        copy = nullptr;
        del  = nullptr;
    }

    LambdaStorage(const LambdaStorage& other)
    {
        call = other.call;
        copy = other.copy;
        del  = other.del ;
        copy(data, other.data);
    }

    LambdaStorage& operator=(const LambdaStorage& other) = delete;

    R operator()(Args... args)
    {
        return call(data, args...);
    }

private:
    template<class F>
    static R CallImpl(const char* data, Args... args)
    {
        const F* f = reinterpret_cast<const F*>(data);
        return (*f)(args...);
    }

    template<class F>
    static void CopyImpl(char* dest, const char* src)
    {
        const F* f = reinterpret_cast<const F*>(src);
        new (dest) F(*f);
    }

    template<class F>
    static void DelImpl(char* data)
    {
        const F* f = reinterpret_cast<const F*>(data);
        f->~F();
    }

    R    (*call) (const char* data, Args...);
    void (*copy) (char* dest, const char* src);
    void (*del)  (char* data);

    char data[BufferSize];
};

typedef LambdaStorage<16, int, const char*, int> MyCallable;

MyCallable MakeCallable()
{
    int i = 22;
    return [i](const char* s, int j)
    {
        std::cout << s << '\n';
        return (i+j);
    };
}

void UseCallable(MyCallable c)
{
    int r = c("Hello world!", 20);
    std::cout << "Result " << r << '\n';
}

int main()
{
    MyCallable c = MakeCallable();
    UseCallable(c);
    return 0;
}
Re[5]: Связать лямбду
Здравствуйте, Marty, Вы писали:

M>Кучи нет. Кстати


Ого. Ну как-то так можно, раз new запрещён, остаётся фиксированный буфер в себе:

template<std::size_t BufferSize, class R, class... Args>
class LambdaStorage
{
public:
    template<class F>
    LambdaStorage(F f)
    {
        new (data) F(f);
        call = CallImpl<F>;
        copy = CopyImpl<F>;
        del  = DelImpl<F>;        
    }

    LambdaStorage()
    {
        call = nullptr;
        copy = nullptr;
        del  = nullptr;
    }

    LambdaStorage(const LambdaStorage& other)
    {
        call = other.call;
        copy = other.copy;
        del  = other.del ;
        copy(data, other.data);
    }

    ~LambdaStorage()
    {
        if ( del != nullptr )
            del(data);
    }

    LambdaStorage& operator=(const LambdaStorage& other) = delete;

    R operator()(Args... args)
    {
        return call(data, args...);
    }

private:
    template<class F>
    static R CallImpl(const char* data, Args... args)
    {
        const F* f = reinterpret_cast<const F*>(data);
        return (*f)(args...);
    }

    template<class F>
    static void CopyImpl(char* dest, const char* src)
    {
        const F* f = reinterpret_cast<const F*>(src);
        new (dest) F(*f);
    }

    template<class F>
    static void DelImpl(char* data)
    {
        const F* f = reinterpret_cast<const F*>(data);
        f->~F();
    }

    R    (*call) (const char* data, Args...);
    void (*copy) (char* dest, const char* src);
    void (*del)  (char* data);

    char data[BufferSize];
};

typedef LambdaStorage<16, int, const char*, int> MyCallable;

MyCallable MakeCallable()
{
    int i = 22;
    return [i](const char* s, int j)
    {
        std::cout << s << '\n';
        return (i+j);
    };
}

void UseCallable(MyCallable c)
{
    int r = c("Hello world!", 20);
    std::cout << "Result " << r << '\n';
}

int main()
{
    MyCallable c = MakeCallable();
    UseCallable(c);
    return 0;
}