将 C++ 成员函数指针传递给 STL 算法

Posted

技术标签:

【中文标题】将 C++ 成员函数指针传递给 STL 算法【英文标题】:Passing a C++ Member Function Pointer to an STL Algorithm 【发布时间】:2015-05-20 15:56:41 【问题描述】:

我有一个成员函数如下:

class XYZ
public:
    float function(float x);
private:
    float m_DensityMin;
    float m_DensityMax;
;

现在,我正在尝试使用std::transform STL 算法转换std::vector<float> foo,方法是传递成员函数function,并将结果值存储在向量bar 中。

如果我将该函数用作全局函数,使用应表示类的成员变量的随机数据,它可以正常工作。

但是,由于该函数需要使用类的成员变量m_DensityMinm_DensityMax,所以我需要将其用作成员函数。这是我尝试过的:

std::transform(foo.begin(), foo.end(), bar.begin(), &XYZ::function);

但我最终在 VS2010 中出现错误:

error C2065: term does not evaluate to a function taking 1 arguments

据我所知,我只传递了 1 个参数。任何指针? 这是一个类似的question,我尝试过使用 std::mem_fun,因为我无法使用 std::mem_fn,但无济于事。

【问题讨论】:

“我尝试过使用 std::mem_fun,因为我无法使用 std::mem_fn,但无济于事。” 使用 @987654332 时出现了什么问题@?您是否尝试过使用 lambda? 除非它是一个静态函数,否则您需要一个参数对象,并将其绑定到mem_fun 返回的任何内容:std::transform(foo.begin(), foo.end(), std::back_inserter(bar), std::bind1st(std::mem_fun(&XYZ::function), &xyz));, demo function 应该是静态成员函数。 @Piotr 非常感谢,成功了! @ccoder83 VS2010有mem_fn,试试std::tr1::mem_fn 【参考方案1】:

std::mem_fun 本身只为成员函数提供了一个包装器,因此将在传递给其operator() 的第一个参数的上下文中调用它。话虽如此,在将函数对象传递给std::transform 算法之前,您需要bind 的正确实例XYZ

XYZ xyz;

std::transform(foo.begin(), foo.end(),
               std::back_inserter(bar),
               std::bind1st(std::mem_fun(&XYZ::function), &xyz));
//                  ~~~~~~^      ~~~~~~^                  ~~~^

DEMO

【讨论】:

【参考方案2】:

除非函数是static,否则它需要一个类的实例来调用函数。因为非静态函数应该依赖于该类的内部状态。如果函数独立于类的状态,它可能应该是静态的。

如果您必须按原样保留您的课程,您可以默认构造一个 XYZ 来解决这个问题,只是为了有一个实例来调用函数。

std::transform(foo.begin(),
               foo.end(),
               std::back_inserter(bar),
               [](float a) return XYZ.function(a); );

但这感觉很hacky,如果函数不依赖于XYZ 实例的状态,我希望函数是static,并且只依赖于输入float

【讨论】:

foovector<float>,而不是 vector<XYZ> 比起 std::bind,我更喜欢 lambda 版本。我实际上忘记了 std::bind ,因为我学习了 lambda,现在我更快乐了!我也喜欢您在适当位置创建微小对象的事实,尽管如果它的大小相关,通过引用捕获它可能会更好。 如果函数依赖于 XYZ 实例的状态,您可以使用 lambda 绑定到您调用 std::transform 的同一个 XYZ 实例。 std::transform(foo.begin(), foo.end(), std::back_inserter(bar), [this](float a) return this->function(a); )【参考方案3】:

lambda 版本

std::vector<float> foo;
std::vector<float> bar;
foo.push_back(1.0f);
foo.push_back(2.0f);
XYZ xyz;
std::transform(foo.begin(), foo.end(), std::back_inserter(bar), 
        [&xyz](float& a) return xyz.function(a); );
 for ( auto & x : bar)
   std::cout<<x<<"\n";

【讨论】:

以上是关于将 C++ 成员函数指针传递给 STL 算法的主要内容,如果未能解决你的问题,请参考以下文章

提升 C++。将带有签名指针的成员函数指针传递给函数

如何将函数指针传递给成员函数c++?

C++成员函数指针指向全局函数指针

在 C++ 中将指向基类的指针传递给派生类的成员函数

C++ Primer 5th笔记(chap 19 特殊工具与技术)将成员函数用作可调用对象

C++函数指针与成员函数指针