简体   繁体   中英

error defining std::function pointer to an instance of a function template, which is a member of a templated class?

I'm getting the following error trying to declare an std::function pointing to a templated class member.

Error C2672 ' std::invoke ': no matching overloaded function found

template <typename InputArchive, typename OutputArchive, typename ... Components>
class LevelSerializer {
...
    template <typename Component>
    void initRegistry() {
        ...
        std::function<void(entityx::Entity, OutputArchive)> f(std::bind(&LevelSerializer<InputArchive, OutputArchive, Components...>::saveComponent<Component>, this)); // errors
    }

    ...
    // I'm trying to point to an instance of this function
    template <typename T>
    void saveComponent(entityx::Entity& entity, OutputArchive& archive)
};

entityx::Entity is a fixed (non-template) type. Why does doing this fail?

You have two problems: Firstly, your line:

   std::function<void(entityx::Entity, OutputArchive)> 
       f(std::bind(&LevelSerializer<InputArchive, OutputArchive, Components...>::saveComponent<Component>, this)); // errors

should be

   typedef std::function<void(entityx::Entity, OutputArchive) functype;
   typedef LevelSerializer<InputArchive, OutputArchive, Components...> LS;

   functype f(std::bind(&LS::saveComponent<Component>, this, 
                                          std::placeholders::_1, std::placeholders::_2 ));

Your problem is that as you have written it, your call to std::bind is trying to return aa function with no arguments (and it ends up not having enough arguments for the member function you are trying to call). You need to bind in the place holder arguments so that a) the member function has enough arguments; b) the result is a thing that has two arguments.

As an aside: Inside the LevelSerializer template, a naked LevelSerializer refers to the template with its arguments. So actually, you just need:

   typedef std::function<void(entityx::Entity, OutputArchive) functype;

   functype f(std::bind(&LevelSerializer::saveComponent<Component>, this, 
                                          std::placeholders::_1, std::placeholders::_2 ));

Your second problem is that the signatures don't match (thanks to Piotr Skotnicki for this). The template argument to function is for a function that takes two parameters by value . Your member function takes two arguments by non-const reference . You need to change at least the template argument to:

   typedef std::function<void(entityx::Entity&, OutputArchive&) functype;

   functype f(std::bind(&LevelSerializer::saveComponent<Component>, this, 
                                          std::placeholders::_1, std::placeholders::_2 ));

... but you might want to change the entity argument to be by const reference.

Martin Bonner addressed the question more directly, but I thought I'd note that in my case I received this error for the following code:

std::bind(&ClassName::FuncName, objName, _1);

And fixed it like so:

std::bind(&ClassName::FuncName, objName, std::placeholders::_1);

Apparently one of my headers included a boost library with placeholders, and _1 was pointing to the boost version instead of my version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM