sazr
sazr

Reputation: 25928

Using std::placeholders in variadic templates

I am having difficulty using std::placeholders in my function that takes a variadic template. I am starting to think I don't need to use a variadic template, but I've been trying this for so long I'm thinking in the weeds and need someone with a fresh look.

The following templated function takes a regular templated argument and then a variadic argument. It is causing a compiler error:

registerEvent<UpdaterComponent, std::_Ph<1>>(EVT_INIT, &UpdaterComponent::initialise, std::placeholders::_1); 

Compiler error:

Error 1 error C2664: 'Status Component::registerEvent>(const int &,Status UpdaterComponent::* (__cdecl )(const EventArgs &),std::_Ph<1>)' : cannot convert argument 2 from 'Status (__thiscall UpdaterComponent:: )(const EventArgs &)' to 'Status UpdaterComponent::* (__cdecl *)(const EventArgs &)'

What exactly is going wrong here and how I can fix this compiler error?

// In class Component
template<typename T, typename... Params>
Status registerEvent(int evtId, Status T::*func(const EventArgs& evtArgs), Params...)
{
    ... irrelevant code removed for brevity

    auto res = std::bind(func, this, Params...);

    ... irrelevant code removed for brevity
}


// Usage
class UpdaterComponent : public Component
{
public:
    UpdaterComponent()
    {
        registerEvent<UpdaterComponent, std::_Ph<1>>(EVT_INIT, &UpdaterComponent::initialise, std::placeholders::_1);
    }
};

Upvotes: 3

Views: 1441

Answers (1)

Barry
Barry

Reputation: 303097

The main problem is that you're missing parentheses:

template<typename T, typename... Params>
Status registerEvent(int evtId, Status (T::*func)(const EventArgs& evtArgs), Params...)
                                      ^^^       ^^^

So you end up getting the type of func wrong.

Once you fix that, why are you explicitly providing all the template parameters? That's what template deduction is for! And when you find yourself typing std::_Ph, don't. This suffices:

registerEvent(EVT_INIT, &UpdaterComponent::initialise, std::placeholders::_1);

Upvotes: 2

Related Questions