Boost logo

Boost :

From: John Torjo (john.lists_at_[hidden])
Date: 2004-08-18 10:30:55


Dear boosters,

Did a lightweight replacement for boost::function (compile-wise). Focus
was on making it very fast to compile.

Rationale: boost::function takes too long to compile. In a library I'm
developing (win32gui), using boost::function would almost double the
compilation time of some headers.

This lightweight replacement takes virtually no extra compilation time.

How I tested it:
I took a project that took 1 minute to compile - added this to all of
the headers, and it compiles in the same amount of time. #including
<boost/function.hpp> almost doubled the time.

Tested with vc71,gcc3.2.

Feel free to use it any way you wish. Any feedback/suggestions deeply
appreciated.

Best,
John

-- 
John Torjo
Freelancer
-- john_at_[hidden]
Contributing editor, C/C++ Users Journal
-- "Win32 GUI Generics" -- generics & GUI do mix, after all
-- http://www.torjo.com/win32gui/
-- v1.3beta released - check out splitter/simple_viewer,
    a File Explorer/Viewer all in about 200 lines of code!
Professional Logging Solution for FREE
-- http://www.torjo.com/code/logging.zip (logging           - C++)
-- http://www.torjo.com/logview/         (viewing/filtering - Win32)
-- http://www.torjo.com/logbreak/        (debugging         - Win32)

#ifndef JOHN_TORJO_WIN32GUI_function
#define JOHN_TORJO_WIN32GUI_function

#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif

// function.hpp

// Win32 GUI Generics library
//
// Copyright (C) 2004 John Torjo (john_at_[hidden])
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// To see the version you have now, read win32gui/version.txt
//
// You can find the latest version of this library at http://www.torjo.com/win32gui/

#include <assert.h>
#include <stdexcept>
// #include <win32gui/.hpp>

namespace win32 { namespace gui {

/*
    Note: removed dependency on boost, and anyway, boost::function does take a lot to compile
*/

// note: removed dependency on boost, that's why we need this
namespace detail {

    struct no_param {};
    template<class func, class base> struct func_exec : base {
        typedef typename base::result res;
        typedef typename base::arg1 arg1;
        typedef typename base::arg2 arg2;
        typedef typename base::arg3 arg3;
        typedef typename base::arg4 arg4;
        typedef typename base::arg5 arg5;

        func_exec(func f) : f(f) {}

        // note: one of these is defined virtual in class base
        res operator()() { return f(); }
        res operator()(const arg1 & a1) { return f(a1); }
        res operator()(const arg1 & a1, const arg2 & a2) { return f(a1,a2); }
        res operator()(const arg1 & a1, const arg2 & a2, const arg3 & a3) { return f(a1,a2,a3); }
        res operator()(const arg1 & a1, const arg2 & a2, const arg3 & a3, const arg4 & a4) { return f(a1,a2,a3,a4); }
        res operator()(const arg1 & a1, const arg2 & a2, const arg3 & a3, const arg4 & a4, const arg5 & a5) { return f(a1,a2,a3,a4,a5); }

        // overrides the base' class
        base * clone() const { return new func_exec<func,base>(*this); }
    private:
        func f;
    };

    template<class res> struct func_keeper0 {
        typedef func_keeper0<res> self;
        typedef res result;
        typedef no_param arg1;
        typedef no_param arg2;
        typedef no_param arg3;
        typedef no_param arg4;
        typedef no_param arg5;

        virtual res operator()() = 0;
        virtual self * clone() const = 0;
    };

    template<class res, class a1> struct func_keeper1 {
        typedef func_keeper1<res,a1> self;
        typedef res result;
        typedef a1 arg1;
        typedef no_param arg2;
        typedef no_param arg3;
        typedef no_param arg4;
        typedef no_param arg5;

        virtual res operator()(const arg1&) = 0;
        virtual self * clone() const = 0;
    };

    template<class res, class a1, class a2> struct func_keeper2 {
        typedef func_keeper2<res,a1,a2> self;
        typedef res result;
        typedef a1 arg1;
        typedef a2 arg2;
        typedef no_param arg3;
        typedef no_param arg4;
        typedef no_param arg5;

        virtual res operator()(const arg1&,const arg2&) = 0;
        virtual self * clone() const = 0;
    };

    template<class res, class a1, class a2, class a3> struct func_keeper3 {
        typedef func_keeper3<res,a1,a2,a3> self;
        typedef res result;
        typedef a1 arg1;
        typedef a2 arg2;
        typedef a3 arg3;
        typedef no_param arg4;
        typedef no_param arg5;

        virtual res operator()(const arg1&,const arg2&, const arg3&) = 0;
        virtual self * clone() const = 0;
    };

    template<class res, class a1, class a2, class a3, class a4> struct func_keeper4 {
        typedef func_keeper4<res,a1,a2,a3,a4> self;
        typedef res result;
        typedef a1 arg1;
        typedef a2 arg2;
        typedef a3 arg3;
        typedef a4 arg4;
        typedef no_param arg5;

        virtual res operator()(const arg1&,const arg2&, const arg3&, const arg4&) = 0;
        virtual self * clone() const = 0;
    };
}

template<class res> struct func_wrapper0 {
    typedef res result;
    typedef detail::no_param arg1;
    typedef detail::no_param arg2;
    typedef detail::no_param arg3;
    typedef detail::no_param arg4;
    typedef detail::no_param arg5;

    typedef detail::func_keeper0<res> func_keeper;
    typedef func_wrapper0<res> self_type;

    func_wrapper0() : m_f(0) {}
    template<class func> func_wrapper0(func f) : m_f(new detail::func_exec<func,func_keeper>(f)) {}

    typedef res (*raw_func)();
    func_wrapper0(raw_func f) : m_f(new detail::func_exec<raw_func,func_keeper>(f)){}

    func_wrapper0(const self_type & other) : m_f(other.m_f ? other.m_f->clone() : 0) {}

    res operator()() {
        if ( m_f) return (*m_f)();
        else WIN32GUI_THROW std::runtime_error("null function");
    }
    self_type& operator=(const self_type & other) {
        func_keeper * old = m_f;
        m_f = other.m_f ? other.m_f->clone() : 0;
        delete old;
        return *this;
    }

private:
    func_keeper * m_f;
};

template<class res,class arg1_type> struct func_wrapper1 {
    typedef res result;
    typedef arg1_type arg1;
    typedef detail::no_param arg2;
    typedef detail::no_param arg3;
    typedef detail::no_param arg4;
    typedef detail::no_param arg5;

    typedef detail::func_keeper1<res,arg1> func_keeper;
    typedef func_wrapper1<res,arg1> self_type;
    typedef res (*raw_func)(const arg1&);

    func_wrapper1() : m_f(0) {}
    template<class func> func_wrapper1(func f) : m_f(new detail::func_exec<func,func_keeper>(f)) {}

    func_wrapper1(raw_func f) : m_f(new detail::func_exec<raw_func,func_keeper>(f)){}
    func_wrapper1(const self_type & other) : m_f(other.m_f ? other.m_f->clone() : 0) {}

    res operator()(const arg1 &a1) {
        if ( m_f) return (*m_f)(a1);
        else WIN32GUI_THROW std::runtime_error("null function");
    }
    self_type& operator=(const self_type & other) {
        func_keeper * old = m_f;
        m_f = other.m_f ? other.m_f->clone() : 0;
        delete old;
        return *this;
    }

private:
    func_keeper * m_f;
};

template<class res,class arg1_type,class arg2_type> struct func_wrapper2 {
    typedef res result;
    typedef arg1_type arg1;
    typedef arg2_type arg2;
    typedef detail::no_param arg3;
    typedef detail::no_param arg4;
    typedef detail::no_param arg5;

    typedef detail::func_keeper2<res,arg1,arg2> func_keeper;
    typedef func_wrapper2<res,arg1,arg2> self_type;
    typedef res (*raw_func)(const arg1&,const arg2&);

    func_wrapper2() : m_f(0) {}
    template<class func> func_wrapper2(func f) : m_f(new detail::func_exec<func,func_keeper>(f)) {}

    func_wrapper2(raw_func f) : m_f(new detail::func_exec<raw_func,func_keeper>(f)){}
    func_wrapper2(const self_type & other) : m_f(other.m_f ? other.m_f->clone() : 0) {}

    res operator()(const arg1 &a1, const arg2 &a2) {
        if ( m_f) return (*m_f)(a1,a2);
        else WIN32GUI_THROW std::runtime_error("null function");
    }
    self_type& operator=(const self_type & other) {
        func_keeper * old = m_f;
        m_f = other.m_f ? other.m_f->clone() : 0;
        delete old;
        return *this;
    }

private:
    func_keeper * m_f;
};

template<class res,class arg1_type,class arg2_type,class arg3_type> struct func_wrapper3 {
    typedef res result;
    typedef arg1_type arg1;
    typedef arg2_type arg2;
    typedef arg3_type arg3;
    typedef detail::no_param arg4;
    typedef detail::no_param arg5;

    typedef detail::func_keeper3<res,arg1,arg2,arg3> func_keeper;
    typedef func_wrapper3<res,arg1,arg2,arg3> self_type;
    typedef res (*raw_func)(const arg1&,const arg2&,const arg3&);

    func_wrapper3() : m_f(0) {}
    template<class func> func_wrapper3(func f) : m_f(new detail::func_exec<func,func_keeper>(f)) {}

    func_wrapper3(raw_func f) : m_f(new detail::func_exec<raw_func,func_keeper>(f)){}
    func_wrapper3(const self_type & other) : m_f(other.m_f ? other.m_f->clone() : 0) {}

    res operator()(const arg1 &a1, const arg2 &a2, const arg3 &a3) {
        if ( m_f) return (*m_f)(a1,a2,a3);
        else WIN32GUI_THROW std::runtime_error("null function");
    }
    self_type& operator=(const self_type & other) {
        func_keeper * old = m_f;
        m_f = other.m_f ? other.m_f->clone() : 0;
        delete old;
        return *this;
    }

private:
    func_keeper * m_f;
};

template<class res,class arg1_type,class arg2_type,class arg3_type,class arg4_type> struct func_wrapper4 {
    typedef res result;
    typedef arg1_type arg1;
    typedef arg2_type arg2;
    typedef arg3_type arg3;
    typedef arg4_type arg4;
    typedef detail::no_param arg5;

    typedef detail::func_keeper4<res,arg1,arg2,arg3,arg4> func_keeper;
    typedef func_wrapper4<res,arg1,arg2,arg3,arg4> self_type;
    typedef res (*raw_func)(const arg1&,const arg2&,const arg3&,const arg4&);

    func_wrapper4() : m_f(0) {}
    template<class func> func_wrapper4(func f) : m_f(new detail::func_exec<func,func_keeper>(f)) {}

    func_wrapper4(raw_func f) : m_f(new detail::func_exec<raw_func,func_keeper>(f)){}
    func_wrapper4(const self_type & other) : m_f(other.m_f ? other.m_f->clone() : 0) {}

    res operator()(const arg1 &a1, const arg2 &a2, const arg3 &a3, const arg4 &a4) {
        if ( m_f) return (*m_f)(a1,a2,a3,a4);
        else WIN32GUI_THROW std::runtime_error("null function");
    }
    self_type& operator=(const self_type & other) {
        func_keeper * old = m_f;
        m_f = other.m_f ? other.m_f->clone() : 0;
        delete old;
        return *this;
    }

private:
    func_keeper * m_f;
};

/*

void f() {
    std::cout << "f" << std::endl;
}
void f1(int i) {
    std::cout << "f1(" << i << ")" << std::endl;
}

bool f2(int i, char c) {
    std::cout << "f2(" << i << "," << c << ")" << std::endl;
    return true;
}

int f3(int i, char c, char d) {
    std::cout << "f3(" << i << "," << c << d << ")" << std::endl;
    return 2;
}

int f4(int i, char c, char d, char e) {
    std::cout << "f4(" << i << "," << c << d << e << ")" << std::endl;
    return 3;
}

struct titi {
    titi() : idx(0) {}

    void operator()() {
        std::cout << "titi" << idx++ << std::endl;
    }

    int idx;
};

int main()
{

    func_wrapper0<void> test(&f);
    test();
    titi t;
    func_wrapper0<void> test2( t );
    test2();
    func_wrapper0<void> test3( test2 );

    test2();
    test2();
    test3();
    func_wrapper0<void> test4;
    test4 = test3;
    test4();
    test4 = test;
    test4();

    func_wrapper1<void,long> func1(f1);
    func1(0);
    func1(2);

    func_wrapper2<int,long,int> func2(f2);
    int i = func2(10,97);
    assert(i == 1);

    func_wrapper3<int,long,int,char> func3(f3);
    i = func3(11,97,'b');
    assert(i == 2);

    func_wrapper4<int,long,int,char,char> func4(f4);
    i = func4(12,97,'b','c');
    assert(i == 3);

    std::cin.get();
        return 0;
}

*/
}}

#endif // JOHN_TORJO_WIN32GUI_function


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk