将std::function添加到C++向量中

3
我有一个包含函数指针的向量。
typedef bool (*fPtr)();
vector<fPtr> AlgoDB;

我将为您进行翻译。以下是我推入向量中的函数定义:

我推入向量中的函数定义如下

bool SAlgos1::Algo1() {
    cout << "Executing Algo1" << endl;
    return true;
} 

以下语句用于将函数/指针添加到向量中。
this->AlgoDB.push_back((fPtr) &this->Algo1);

这是传统的C语言风格的函数指针用法,我想使用 std::function,现在向量和函数已经被修改如下:

typedef function<bool()> ffptr;
vector <ffptr> fAlgoDB;

function<bool()> SAlgos1::fAlgo1(){

    cout << "Executing FAlgo1";
    return true;
}

现在每当我使用以下声明时:

this->fAlgoDB.push_back(fAlgo1);this->fAlgoDB.push_back(&fAlgo1); (强制转换也无济于事 - this->fAlgoDB.push_back((ffptr) this->fAlgo1);

我会收到以下错误提示:

error: taking address of temporary [-fpermissive]

error: could not convert 'true' from 'bool' to 'std::function<bool()>' (即使我实际上没有调用该函数)每次交替编译都会出现。

如何将函数或函数指针存储在向量中?编译器试图传达什么意思?


2
你正在从 fAlgo1 返回一个 std::function,但应该返回一个 bool。此外,你的原始代码甚至不能与成员函数一起使用,因为你必须在函数指针 typedef 中声明类的类型! - Felix Dombek
原始函数可以不使用类类型,但这会导致编译器警告! - Bharadwaj
如果您定义一个函数指针来指向全局函数,但是却使用它来存储成员函数并调用它,则会引发未定义的行为。您的 (fPtr) 强制转换只是隐藏了您正在强制转换不兼容的内容的事实。最好不要使用 C 风格的强制转换! - Felix Dombek
2个回答

6
您的示例存在两个问题。
  1. 您将函数的返回类型从 bool 更改为 function<bool>。请将其保留为 bool,因为这是您想要的返回类型。
  2. 成员函数指针的类型与函数指针的类型不同(请参见https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types)。这是因为成员函数始终将this指针作为参数传递。您需要使用std::bind来绑定该参数(请参见https://dev59.com/wWsz5IYBdhLWcg3w6MJS#7582576)。
下面的示例可以成功编译。
#include <functional>
#include <vector>
#include <iostream>

using namespace std;

class SAlgos1
{
    typedef function<bool()> ffptr;

    bool fAlgo1()
    {
        cout << "Executing FAlgo1";
        return true;
    }

    void fillAlgoDB()
    {
        fAlgoDB.push_back(bind(&SAlgos1::fAlgo1, this));
    }

    vector<ffptr> fAlgoDB;
};

2
我会使用lambda而不是bind。在没有lambda的时候,bind是必需的。现在它只是一个坐在角落里的怪物。自从c++14以来,它已经完全过时了。 - bolov
2
@bolov:只有从C++14开始才支持。问题标记为[tag:c++11],在C++11中,缺乏通用lambda使得std::bind在多种情况下更可取。请注意,这不是其中之一。我想这和你说的差不多。 - Lightness Races in Orbit
@LightnessRacesinOrbit 确切无误 - bolov

1
你正在从 fAlgo1 返回一个 std::function,但应该返回一个 bool。此外,你的原始代码甚至不能与成员函数一起使用,因为你必须在函数指针 typedef 中声明类的类型!
语法在 这里 解释。你可以使用
typedef bool (SAlgos1::*fPtr)();

修复函数指针。

目前,您正在调用未定义的行为,因为您声明一个函数指针指向全局函数,但实际上使用它来存储成员函数,然后调用它。您的(fPtr)强制转换仅隐藏了您正在进行不兼容转换的事实。最好不要使用C风格的转换!


我理解了,返回参数存在错误,因为我不知道如何定义一个实际上是std::function的成员函数的语法。谢谢你的帮助,但是我该如何在向量中定义和推送std::function(成员函数)呢? - Bharadwaj
1
使用 this->AlgoDB.push_back(std::bind(&SAlgos1::fAlgo1, this)); - Felix Dombek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接