定义指向函数模板实例的std::函数指针时出错,该实例是模板化类的成员

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

本文关键字:实例 成员 指针 函数模板 std 函数 定义 出错      更新时间:2023-10-16

我在试图声明一个指向模板化类成员的std::函数时遇到以下错误。

错误C2672"std::invoke":找不到匹配的重载函数

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是一种固定(非模板)类型。为什么这样做会失败?

您有两个问题:首先,您的线路:

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

应该是

   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 ));

您的问题是,正如您所写的那样,您对std::bind的调用试图返回一个没有参数的函数(最终它没有足够的参数用于您试图调用的成员函数)。您需要绑定占位符参数,以便a)成员函数有足够的参数;b) 结果是一件有两个论点的事情。

顺便说一句:在LevelSerializer模板中,一个裸露的LevelSerializer引用了该模板及其参数。所以实际上,你只需要:

   typedef std::function<void(entityx::Entity, OutputArchive) functype;
   functype f(std::bind(&LevelSerializer::saveComponent<Component>, this, 
                                          std::placeholders::_1, std::placeholders::_2 ));

第二个问题是签名不匹配(感谢Piotr Skotnicki)。function的模板参数用于一个函数,该函数按值接受两个参数。您的成员函数通过非常量引用接受两个参数。您至少需要将模板参数更改为:

   typedef std::function<void(entityx::Entity&, OutputArchive&) functype;
   functype f(std::bind(&LevelSerializer::saveComponent<Component>, this, 
                                          std::placeholders::_1, std::placeholders::_2 ));

但您可能希望将entity参数更改为常量引用。

Martin Bonner更直接地回答了这个问题,但我想我应该注意到,在我的情况下,我收到了以下代码的错误:

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

并这样修复:

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

显然,我的一个标题包含一个带有占位符的boost库,而_1指向的是boost版本,而不是我的版本。