0

I have 2 functions inside a class, one is the default specilization of the operator+= which expects a function of some sort, whilst the second specilization expects an EventHandler, here is the implementation:

    template<typename _Func>
    timed_function<_Sig>& operator+=( _Func &&f )
    {
        // Create an unamed handler
        auto handler = new EventHandler<_Sig>( "unamed", std::forward<_Func>( f ) );

        // Push it
        _fs.push_back( handler );

        // Return a reference to the function
        return handler->get( );
    }

Here's the specialized version:

template<>
timed_function<_Sig>& operator+=<const EventHandler<_Sig>&>( const EventHandler<_Sig> &_Handler )
{
    // Copy the handler and push it
    _fs.push_back( new EventHandler<_Sig>( _Handler ) );

    // Return a reference to the function
    return _fs.back( )->get( );
}

Where _fs is just a vector of EventHandler<_Sig> Pointers. And _Sig being the function signature (e.g void(int))

When using the += operator on for example a lambda function it works just fine and the compiler picks the correct specialization:

window->OnKeyDown( ) += []( dx::Window *sender, dx::KeyDownArgs &args )
{
    [...]
};

OnKeyDown( ) returns a reference to an instance of Event<void(dx::Window*, dx::KeyDownArgs&)>

However when I try and manually add an EventHandler like this it still picks the non-specialized version of the function.

window->OnKeyDown( ) += EventHandler<void(dx::Window*, dx::KeyDownArgs&)>( "Key Handler", 
                        []( dx::Window *sender, dx::KeyDownArgs &args ) 
                        {
                            [...]
                        } );

Thanks!

2 Answers2

1

You provide EventHandler<_Sig>&& not a const EventHandler<_Sig>&, so the non specialized version is chosen.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I figured that might be the cause, the question is how would one solve it? Thanks. – user5876769 Apr 05 '16 at 15:28
  • @PsychoBitch, see my answer. – SergeyA Apr 05 '16 at 15:29
  • @PsychoBitch: turning your template to `template timed_function& operator+=(const F& f)` might be a solution. SFINAE and overload an other, or partial spetialisation of (helper) struct. Or be explicit in the call as SergeyA suggests. – Jarod42 Apr 05 '16 at 15:32
0

To properly specialize, just use

template<>
timed_function<_Sig>& operator+=<const EventHandler<_Sig>>...

That is, remove the reference from template specialization. Here is an example of how this sort of specialization should work - with cooked-up types, but should be useful:

http://coliru.stacked-crooked.com/a/297df51929329484

(depending on your compiler, you might have to put a space between '>>' in specialization).

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • Weirdly this causes the same exact error to be triggered around 140 times on the same line. Removing the reference from the specialization causes the compiler so say the specialization is of ill form. @SergeyA – user5876769 Apr 05 '16 at 15:33
  • @PsychoBitch, please provide the full code of the specialization. You definitely have an issue there. – SergeyA Apr 05 '16 at 15:37
  • @PsychoBitch, remove `const` and try putting a space between '>', like ` >` Here is an example (with cooked-up types, just for show): http://coliru.stacked-crooked.com/a/297df51929329484 – SergeyA Apr 05 '16 at 15:39
  • that does not fix it, I'm just gonna do something stupid instead and add a constructor to EventHandler so that the second argument can take EventHandler<_Sig> or directly a function, that way I dont need specialization. – user5876769 Apr 05 '16 at 15:42
  • @PsychoBitch, suit yourself, but this specialization should work. Check the example I provided. – SergeyA Apr 05 '16 at 15:43
  • edit that in to your post and I'll mark it as the answer! – user5876769 Apr 05 '16 at 15:45
  • yes, just needed to change the Non-specialized version to also take a const T&, I guess universal references was the main issue. – user5876769 Apr 05 '16 at 15:51