|
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