Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7502305
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 29, 20262026-05-29T20:49:16+00:00 2026-05-29T20:49:16+00:00

I’m porting FastDelegate to C++0x using variadic templates. #include FastDelegate.h template<class R=fastdelegate::detail::DefaultVoid, class …P>

  • 0

I’m porting FastDelegate to C++0x using variadic templates.

    #include "FastDelegate.h"

    template<class R=fastdelegate::detail::DefaultVoid, class ...P>
    class fast_delegate_base {
    private:
        typedef typename fastdelegate::detail::DefaultVoidToVoid<R>::type desired_ret_t;
        typedef desired_ret_t (*static_func_ptr)(P...);
        typedef R (*unvoid_static_func_ptr)(P...);
        typedef R (fastdelegate::detail::GenericClass::*generic_mem_fn)(P...);
        typedef fastdelegate::detail::ClosurePtr<generic_mem_fn, static_func_ptr, unvoid_static_func_ptr> closure_t;
        closure_t closure_;
    public:
        // Typedefs to aid generic programming
        typedef fast_delegate_base type;

        // Construction and comparison functions
        fast_delegate_base() { clear(); }

        fast_delegate_base(const fast_delegate_base &x)
        {
            closure_.CopyFrom(this, x.closure_);
        }

        void operator = (const fast_delegate_base &x)
        {
            closure_.CopyFrom(this, x.closure_);
        }
        bool operator ==(const fast_delegate_base &x) const
        {
            return closure_.IsEqual(x.closure_);
        }
        bool operator !=(const fast_delegate_base &x) const
        {
            return !closure_.IsEqual(x.closure_);
        }
        bool operator <(const fast_delegate_base &x) const
        {
            return closure_.IsLess(x.closure_);
        }
        bool operator >(const fast_delegate_base &x) const
        {
            return x.closure_.IsLess(closure_);
        }

        // Binding to non-const member functions
        template<class X, class Y>
        fast_delegate_base(Y *pthis, desired_ret_t (X::* function_to_bind)(P...) )
        {
            closure_.bindmemfunc(fastdelegate::detail::implicit_cast<X*>(pthis), function_to_bind);
        }

        template<class X, class Y>
        inline void bind(Y *pthis, desired_ret_t (X::* function_to_bind)(P...))
        {
            closure_.bindmemfunc(fastdelegate::detail::implicit_cast<X*>(pthis), function_to_bind);
        }

        // Binding to const member functions.
        template<class X, class Y>
        fast_delegate_base(const Y *pthis, desired_ret_t (X::* function_to_bind)(P...) const)
        {
            closure_.bindconstmemfunc(fastdelegate::detail::implicit_cast<const X*>(pthis), function_to_bind);
        }

        template<class X, class Y>
        inline void bind(const Y *pthis, desired_ret_t (X::* function_to_bind)(P...) const)
        {
            closure_.bindconstmemfunc(fastdelegate::detail::implicit_cast<const X *>(pthis), function_to_bind);
        }

        // Static functions. We convert them into a member function call.
        // This constructor also provides implicit conversion
        fast_delegate_base(desired_ret_t (*function_to_bind)(P...) )
        {
            bind(function_to_bind);
        }

        // for efficiency, prevent creation of a temporary
        void operator = (desired_ret_t (*function_to_bind)(P...) )
        {
            bind(function_to_bind);
        }

        inline void bind(desired_ret_t (*function_to_bind)(P...))
        {
            closure_.bindstaticfunc(this, &fast_delegate_base::invoke_static_func, function_to_bind);
        }

        // Invoke the delegate
        template<typename ...A>
        R operator()(A&&... args) const
        {
            return (closure_.GetClosureThis()->*(closure_.GetClosureMemPtr()))(std::forward<A>(args)...);
        }
        // Implicit conversion to "bool" using the safe_bool idiom

    private:
        typedef struct safe_bool_struct
        {
            int a_data_pointer_to_this_is_0_on_buggy_compilers;
            static_func_ptr m_nonzero;
        } useless_typedef;
        typedef static_func_ptr safe_bool_struct::*unspecified_bool_type;
    public:
        operator unspecified_bool_type() const { return empty()? 0: &safe_bool_struct::m_nonzero; }
        // necessary to allow ==0 to work despite the safe_bool idiom
        inline bool operator==(static_func_ptr funcptr) { return closure_.IsEqualToStaticFuncPtr(funcptr); }
        inline bool operator!=(static_func_ptr funcptr) { return !closure_.IsEqualToStaticFuncPtr(funcptr); }
        // Is it bound to anything?
        inline bool operator ! () const { return !closure_; }
        inline bool empty() const { return !closure_; }
        void clear() { closure_.clear();}
        // Conversion to and from the DelegateMemento storage class
        const fastdelegate::DelegateMemento & GetMemento() { return closure_; }
        void SetMemento(const fastdelegate::DelegateMemento &any) { closure_.CopyFrom(this, any); }

    private:
        // Invoker for static functions
        R invoke_static_func(P... args) const
        {
            return (*(closure_.GetStaticFunction()))(args...);
        }
    };

    // fast_delegate<> is similar to std::function, but it has comparison operators.
    template<typename _Signature>
    class fast_delegate;

    template<typename R, typename ...P>
    class fast_delegate<R(P...)> : public fast_delegate_base<R, P...>
    {
    public:
        typedef fast_delegate_base<R, P...> BaseType;

        fast_delegate() : BaseType() { }

        template<class X, class Y>
        fast_delegate(Y * pthis, R (X::* function_to_bind)(P...))
            : BaseType(pthis, function_to_bind)
        { }

        template<class X, class Y>
        fast_delegate(const Y *pthis, R (X::* function_to_bind)(P...) const)
            : BaseType(pthis, function_to_bind)
        { }

        fast_delegate(R (*function_to_bind)(P...))
            : BaseType(function_to_bind)
        { }

        void operator = (const BaseType &x)
        {
            *static_cast<BaseType*>(this) = x;
        }
    };

But, one of the limitations of my implementation is, when using non-member functions, and in case that function accepts parameter(s) by value, an extra value copy for each parameters take place. I assume that this occurs between fast_delegate_base::operator()() and fast_delegate_base::invoke_static_func().

I tried to make fast_delegate_base::invoke_static_func() to accept Rvalue parameters, but failed.

For example:

class C1
{
public:
    C1() { printf("C1()\n"); }
    ~C1() { printf("~C1()\n"); }
    C1(const C1&)
    {
        printf("C1(const C1&)\n");
    }

    int test(int t) const
    {
        printf("C1::test(%d)\n", t);
        return 1;
    }
};

int test(C1 c)
{
    c.test(1234);
    return 1;
}

// ...

C1 c1;
fast_delegate<int(C1)> t1(test);
t1(c1);

Result of this code is:

C1()
C1(const C1&)
C1(const C1&)
C1::test(1234)
~C1()
~C1()
~C1()

Do you have any idea to avoid this extra value copy?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-29T20:49:17+00:00Added an answer on May 29, 2026 at 8:49 pm

    It looks to me like this copy is inherent in the design of the class, specifically the existence of invoke_static_func.

    From what I can see, this is a proxy to normalize static functions and member functions into just member functions, so they every dispatch can be done as a member function call. The only difference is that the member is the fast_delegate_base instance rather than an instance of whatever class the target function is a member of.

    So there’s an extra call frame when calling static functions, and to get rid of that extra copy you would need to make the extra call frame (invoke_static_func) take its parameter by a reference (ignore for now the consequences of this if the argument type is not a value).

    Unfortunately, invoke_static_func needs to be called via a function pointer which has an argument list containing value types, so operator() is forced to make a copy in order to invoke the function pointer (i.e. to invoke invoke_static_func). Making invoke_static_func take parameters by reference doesn’t help, because it still has to be invoked via a function pointer that does not have reference argument types.

    And there’s no way invoke_static_func can avoid making a copy to call test(C1), that’s just a simple call by value – so you need both copies to make this design work.


    To explain it from a different perspective, thin of it in terms of pure C:

    Operator() needs to call a function func (this_ptr, arg_1, arg_2, arg_3). The target function will expect these parameters to be in particular registers or particular stack locations depending on their position in the argument list and size.

    But a static function does not have the magic first ‘this’ parameter, its signature is just func(arg_1, arg_2, arg_3). So it expects all the other arguments to be in different registers and/or stack locations than the corresponding member function does. So you need that copy to move the arguments into the right registers/stack locations to comply with the calling convention for the static function.

    Which basically, means you can’t avoid that second copy for a static function with this design.


    However… you may be able to improve on this by some crafty template metaprogramming to apply std::move to value type arguments in the implementation of invoke_static_func, reducing your call overhead to a copy and a move, which is almost as good as just one copy.

    I’ll update this answer if and when I figure whether that’s possible (and if so how).


    Edit

    Something like this should do the trick:

    template <bool IsClass, class U>
    struct move_if_class
    {
        template <typename T>
        T&& operator()(const T& t) { return std::move(const_cast<T&>(t)); }
    };
    
    template <class T>
    struct move_if_class<false,T>
    {
        T&& operator()(typename std::remove_reference<T>::type& t) { return std::forward<T>(t); }
        T&& operator()(typename std::remove_reference<T>::type&& t) { return std::forward<T>(t); }
    };
    
    R invoke_static_func(P... args) const
    {
        return (*(closure_.GetStaticFunction()))(move_if_class<std::is_class<P>::value,P>()(args)...);
    }   
    

    And after adding a move c’tor:

    C1()
    C1(const C1&)
    C1(C1&&)
    C1::test(1234)
    ~C1()
    ~C1()
    ~C1()
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I'm using v2.0 of ClassTextile.php, with the following call: $testimonial_text = $textile->TextileRestricted($_POST['testimonial']); ... and
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
We're building an app, our first using Rails 3, and we're having to build
We are using XSLT to translate a RIXML file to XML. Our RIXML contains
I have thousands of HTML files to process using Groovy/Java and I need to
I am using Paperclip to handle profile photo uploads in my app. They upload
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I am reading a book about Javascript and jQuery and using one of the

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.