lightweight replacement for boost::function

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@torjo.com 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@torjo.com) // // 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

"John Torjo" <john.lists@torjo.com> wrote in message news:4123762F.5060101@torjo.com... | Dear boosters, | | Did a lightweight replacement for boost::function (compile-wise). Focus | was on making it very fast to compile. Have you tested normal code on a compiler with precompiled headers? I can include seriously large headers faster than compiling simple code again. I have long been wanting to use <boost/std.hpp> <boost/boost.hpp>. Unfortunately there doesn't seem to be a portable way to create/use PCH. Or did bjam already support this? br Thorsten

Thorsten Ottosen wrote:
"John Torjo" <john.lists@torjo.com> wrote in message news:4123762F.5060101@torjo.com... | Dear boosters, | | Did a lightweight replacement for boost::function (compile-wise). Focus | was on making it very fast to compile.
Have you tested normal code on a compiler with precompiled headers? I can include seriously large headers faster than compiling simple code again.
Yes, I know about precompiled headers. It's just that I can't assume everyone using win32gui will use them. That's the problem ;) Which brings me to another question: does gcc support precompiled headers?
I have long been wanting to use <boost/std.hpp> <boost/boost.hpp>.
True ;) Best, John -- John Torjo Freelancer -- john@torjo.com 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)

John Torjo wrote:
Thorsten Ottosen wrote:
"John Torjo" <john.lists@torjo.com> wrote in message news:4123762F.5060101@torjo.com... | Dear boosters, | | Did a lightweight replacement for boost::function (compile-wise). Focus | was on making it very fast to compile.
Have you tested normal code on a compiler with precompiled headers? I can include seriously large headers faster than compiling simple code again.
Yes, I know about precompiled headers. It's just that I can't assume everyone using win32gui will use them. That's the problem ;)
Which brings me to another question: does gcc support precompiled headers?
Yes, GCC 3.4 has PCH. However, it does not yet work on all GCC targets. In particular, GCC on Windows won't support PCH until GCC 3.5 probably. Aaron W. LaFramboise

Yes, GCC 3.4 has PCH. However, it does not yet work on all GCC targets. In particular, GCC on Windows won't support PCH until GCC 3.5 probably.
Well, I'm sure looking forward to that. GCC is quite slow when it comes to compiling. Best, John -- John Torjo Freelancer -- john@torjo.com 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)

John Torjo wrote:
Dear boosters,
Did a lightweight replacement for boost::function (compile-wise). Focus was on making it very fast to compile.
Forgot to remove some namespaces, etc. ;) Here it is again. -- John Torjo Freelancer -- john@torjo.com 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 // // Copyright (C) 2004 John Torjo (john@torjo.com) // // 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. // #include <assert.h> #include <stdexcept> // #include <win32gui/.hpp> 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 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 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 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 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 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
participants (4)
-
Aaron W. LaFramboise
-
Doug Gregor
-
John Torjo
-
Thorsten Ottosen