Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standalone implementation of std::function?

I'm working on an embedded system, so code size is an issue. Using the standard library ups my binary size by about 60k, from 40k to 100k. I'd like to use std::function, but I can't justify it for 60k. Is there a standalone implementation that I can use, or something similar? I'm using it to implicitly cast lambdas in member functions with bound variables in c++ 11.

like image 219
Kendrick Taylor Avatar asked Feb 06 '13 22:02

Kendrick Taylor


People also ask

What are standalone functions?

A standalone function is a function (a subprogram that returns a single value) that is stored in the database. Note: A standalone function that you create with the CREATE FUNCTION statement differs from a function that you declare and define in a PL/SQL block or package.

Does std :: function allocate?

As it happens, std::function is guaranteed to not allocate if constructed from a function pointer, which is also one word in size. So constructing a std::function from this kind of lambda, which only needs to capture a pointer to an object and should also be one word, should in practice never allocate.

What is a stand alone statement in C++?

A stand-alone function is just a normal function that is not a member of any class and is in a global namespace. For example, this is a member function: class SomeClass { public: SomeClass add( SomeClass other ); }; SomeClass::add( SomeClass other ) { <...> }

Can std :: function be copied?

You can recover the desired behavior by always using thread-local copies of the std::function because they'll each have an isolated copy of the state variables.


2 Answers

The 60k came from exception handling being added by the compiler, because exceptions were required for std::function. std::function only throws one exception, "bad_function_call". So I removed the code that threw the exception, now it seg faults if an empty function is called, and I saved myself 60k.

like image 140
Kendrick Taylor Avatar answered Sep 30 '22 21:09

Kendrick Taylor


Here is simple implementation of std::function-like class template without inclusion of any headers. You can customize the behavior as you wish(like move/forward, empty call response, etc):

live_demo

// Scroll down for example of usage
namespace bicycle
{
    template<typename Result,typename ...Args>
    struct abstract_function
    {
        virtual Result operator()(Args... args)=0;
        virtual abstract_function *clone() const =0;
        virtual ~abstract_function() = default;
    };

    template<typename Func,typename Result,typename ...Args>
    class concrete_function: public abstract_function<Result,Args...>
    {
        Func f;
    public:
        concrete_function(const Func &x)
            : f(x)
        {}
        Result operator()(Args... args) override
        {
            return f(args...);
        }
        concrete_function *clone() const override
        {
            return new concrete_function{f};
        }
    };

    template<typename Func>
    struct func_filter
    {
        typedef Func type;
    };
    template<typename Result,typename ...Args>
    struct func_filter<Result(Args...)>
    {
        typedef Result (*type)(Args...);
    };

    template<typename signature>
    class function;

    template<typename Result,typename ...Args>
    class function<Result(Args...)>
    {
        abstract_function<Result,Args...> *f;
    public:
        function()
            : f(nullptr)
        {}
        template<typename Func> function(const Func &x)
            : f(new concrete_function<typename func_filter<Func>::type,Result,Args...>(x))
        {}
        function(const function &rhs)
            : f(rhs.f ? rhs.f->clone() : nullptr)
        {}
        function &operator=(const function &rhs)
        {
            if( (&rhs != this ) && (rhs.f) )
            {
                auto *temp = rhs.f->clone();
                delete f;
                f = temp;
            }
            return *this;
        }
        template<typename Func> function &operator=(const Func &x)
        {
            auto *temp = new concrete_function<typename func_filter<Func>::type,Result,Args...>(x);
            delete f;
            f = temp;
            return *this;
        }
        Result operator()(Args... args)
        {
            if(f)
                return (*f)(args...);
            else
                return Result{};
        }
        ~function()
        {
            delete f;
        }
    };
}

// ___________________[ Example of usage ]___________________ //

int func1(double)
{
    return 1;
}
struct Functor2
{
    int operator()(double)
    {
        return 2;
    }
};

double func3(bool,int)
{
    return 3.0;
}
struct Functor4
{
    double operator()(bool,int)
    {
        return 4.0;
    }
};

int main()
{
    int res = 10;
    {
        bicycle::function<int(double)> f{func1};

        res -= f(1.0);
        f = Functor2{};
        res -= f(2.0);
    }
    {
        bicycle::function<double(bool,int)> f1;
        f1 = func3;

        bicycle::function<double(bool,int)> f2{f1};
        res -= f2(true,1);

        f1 = Functor4{};
        f2 = f1;
        res -= f2(false,2);
    }
    return res;
}
like image 23
Evgeny Panasyuk Avatar answered Sep 30 '22 19:09

Evgeny Panasyuk