@@ -18,14 +18,18 @@ namespace nodepp { template< class V, class... T > class function_t {
1818public:
1919
2020 template < class F >
21- function_t ( F f ) : func_ptr( new func_impl<F>(f) ) {}
21+ function_t ( const F& f ) : func_ptr( new func_impl<F>(f) ) {}
2222
2323 function_t ( null_t ) noexcept : func_ptr(nullptr ) {}
2424
2525 function_t () noexcept : func_ptr(nullptr ) {}
2626
2727 /* ─······································································─*/
2828
29+ explicit operator bool (void ) const noexcept { return func_ptr.null (); }
30+
31+ /* ─······································································─*/
32+
2933 bool has_value () const noexcept { return func_ptr.has_value (); }
3034 ulong count () const noexcept { return func_ptr.count (); }
3135 bool empty () const noexcept { return func_ptr.null (); }
@@ -34,30 +38,62 @@ namespace nodepp { template< class V, class... T > class function_t {
3438 void clear () const noexcept { /* --*/ func_ptr.free (); }
3539
3640 /* ─······································································─*/
37-
38- explicit operator bool (void ) const noexcept { return func_ptr.null (); }
3941
40- V operator ()( const T&... arg ) const /* ----*/ { return emit ( arg... ); }
42+ template < typename U = V >
43+ typename type::enable_if< type::is_same<U,void >::value, U >::type
44+ operator ()( const T&... arg ) const { emit ( arg... ); }
45+
46+ template < typename U = V >
47+ typename type::enable_if< type::is_same<U,void >::value, U >::type
48+ emit ( const T&... arg ) const { if ( has_value () ){
49+ func_ptr->invoke ( (void *) nullptr , arg... );
50+ }}
51+
52+ /* ─······································································─*/
53+
54+ template < typename U = V >
55+ typename type::enable_if< !type::is_same<U,void >::value, U >::type
56+ operator ()( const T&... arg ) const { return emit ( arg... ); }
4157
42- V emit ( const T&... arg ) const {
43- if ( !has_value () ){ return V (); }
44- return func_ptr->invoke ( arg... );
45- }
58+ template < typename U = V >
59+ typename type::enable_if< !type::is_same<U,void >::value, U >::type
60+ emit ( const T&... arg ) const { U out; if ( has_value () ){
61+ func_ptr->invoke ( &out, arg... );
62+ } return out; }
4663
4764private:
4865
4966 class func_base { public:
50- virtual ~func_base () { /* ----------------- */ }
51- virtual V invoke ( const T&... arg ) const = 0;
67+ virtual ~func_base () {}
68+ virtual void invoke ( V*, const T&... ) const {}
5269 };
5370
5471 /* ─······································································─*/
5572
5673 template < class F >
57- class func_impl : public func_base { private: ptr_t <F> func; public:
58- func_impl ( const F& f ) : func( type::bind( f ) ) { /* -----------*/ }
59- virtual V invoke ( const T&... arg ) const { return (*func)(arg...); }
60- };
74+ class func_impl : public func_base { private:
75+
76+ template < typename U = V >
77+ typename type::enable_if< type::is_same<U,void >::value, void >::type
78+ invoker_helper ( U*, ptr_t <F> cb, const T&... args ) const noexcept {
79+ (*cb)( args... );
80+ }
81+
82+ template < typename U = V >
83+ typename type::enable_if< !type::is_same<U,void >::value, void >::type
84+ invoker_helper ( U* dst, ptr_t <F> cb, const T&... args ) const noexcept {
85+ *dst = (*cb)( args... );
86+ }
87+
88+ public:
89+
90+ virtual void invoke ( V* out, const T&... arg ) const override {
91+ invoker_helper ( out, func, arg... );
92+ }
93+
94+ func_impl ( const F& f ) : func( type::bind(f) ) {}
95+
96+ private: ptr_t <F> func; };
6197
6298 /* ─······································································─*/
6399
0 commit comments