保存类模板化函数指针内映射

c++ save class templated function pointer inside map

本文关键字:指针 映射 函数 保存      更新时间:2023-10-16

我有一个小问题,我无法理解。我有一个函数,看起来像这样:

template <typename T>
std::unique_ptr<Environment>& CreateEnvironment(sf::Vector2f& _position, bool _addToStatic = false);

这是函数指针typepedef

typedef std::unique_ptr<Environment>& (WorldEditor::*CreateEnvironmentPtr)(sf::Vector2f&, bool);
std::map<std::string,CreateEnvironmentPtr> listEnv;

我试着简单地这样做:

listEnv["test"] = &CreateEnvironment<Coin>(sf::Vector2f(200,200), false);

,我得到以下错误:

error C2440: '=' : cannot convert from 'std::unique_ptr<_Ty> *' to 'std::unique_ptr<_Ty> &(__thiscall WorldEditor::* )(sf::Vector2f &,bool)'

我明白错误在说什么,但我不知道如何解决它。另外,当我指向函数的地址时,为什么它甚至关心返回类型?

致以最亲切的问候尼洛

使用std::function通常可以更好地解决此类问题

std::map<std::string, std::function<void()> listEnv;
listEnv.emplace("test", [] {
  CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
});

调用:

listEnv.at("test")->second();

根据你的帖子,我不确定你是否试图在CreateEnvironment类内部或外部创建成员函数指针和映射,所以我将解决我认为是指向单独对象的成员函数的更困难的问题。

我这样简化了你的类:

环境

struct Environment
{
    int i = 1;
};
硬币

struct Coin
{
    int k = 0;
};

WorldEditor

struct WorldEditor
{
    template <typename T>
    std::unique_ptr<Environment> CreateEnvironment(int& _j, bool _addToStatic = false)
    {
        return std::make_unique<Environment>();
    }
};
解决方案:映射对象的成员fn指针,然后稍后调用它

(我将使用c++ 11/14语法在我的回答)

//declare a pointer to member function in WorldEditor
using CreateEnvironmentPtr = std::unique_ptr<Environment> (WorldEditor::*)(int&, bool);
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to the CreateEnvironment<Coin> function
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = &WorldEditor::CreateEnvironment<Coin>;
// call the member function pointer using the instance I created, as well as
// the mapped function
(myWorldEditor.*listEnv["test"])(myInt, false);
// (printing member value to cout to show it worked)
std::cout << (myWorldEditor.*listEnv["test"])(myInt, false)->i << std::endl; // prints 1

现场演示


方案2:使用std::bind和std::function

在创建map的表项时,可能已经知道成员函数调用的形参。使用std::bindstd::function将帮助我们实现这一点(类似于Richard Hodges的解决方案):

// now our "function pointer" is really just a std::function that takes no arguments
using CreateEnvironmentPtr = std::function<std::unique_ptr<Environment>(void)>;
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to that function pointer
//ensure it gets called with the right args 
// by using std::bind (which will also make the arg list appear the be void at call time)
// note that std::bind needs an instance of the class immediately after
// listing the function it should be binding
// only afterwards will we then pass the int& and bool
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = std::bind(&WorldEditor::CreateEnvironment<Coin>, &myWorldEditor, myInt, false);
// the mapped function
listEnv["test"]()->i;
// (printing resulting unique_ptr<Environment>'s member to cout to show it worked)
std::cout << listEnv["test"]()->i << std::endl; // prints 1

Live Demo 2