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

6

我有一个如下的成员函数:

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

现在,我正在尝试使用std::transform STL算法通过传递成员函数function来转换std::vector<float> foo,并将结果存储在向量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

据我所知,我只传递了一个参数。有什么指针吗? 这里有一个类似的问题,我尝试使用std::mem_fun,因为std::mem_fn对我不可用,但是没有成功。

1
“我已经尝试使用std::mem_fun,因为std::mem_fn对我不可用,但是没有成功。” 使用std::mem_fun时出现了什么问题?您是否尝试使用lambda表达式? - dyp
1
除非它是静态函数,否则你需要一个参数对象,并将其绑定到mem_fun返回的任何内容:std ::transform(foo.begin(),foo.end(),std ::back_inserter(bar),std ::bind1st(std ::mem_fun(&XYZ ::function),&xyz));演示 - Piotr Skotnicki
1
“function” 应该是一个静态成员函数。 - David G
@Piotr 太感谢了,那个起作用了! - ccoder83
@ccoder83,VS2010有mem_fn,请尝试使用std::tr1::mem_fn - Praetorian
3个回答

9

std::mem_fun本身仅提供成员函数的包装器,以便在其operator()中调用第一个参数的上下文中调用它。话虽如此,在将函数对象传递给std::transform算法之前,您需要绑定适当的XYZ实例:

XYZ xyz;

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

演示


1

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

如果您必须保留原始类,您可以通过默认构造一个XYZ来绕过此问题,只是为了拥有一个实例来调用该函数。

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

但这种做法感觉很不专业,如果函数独立于XYZ实例的状态,只依赖于输入的float变量,那么最好将其声明为static函数。


foo 是一个 vector<float>,而不是 vector<XYZ> - David G
我更喜欢lambda版本,而不是std::bind。自从学习了lambda之后,我实际上忘记了std::bind,现在我感到更加快乐!我也喜欢这个事实,即你可以直接创建一个小对象,尽管如果它的大小相关,最好通过引用来捕获它。 - DarioP
1
如果函数依赖于XYZ实例的状态,您可以使用lambda绑定到与您从中调用std :: transform的XYZ实例相同的实例。 std :: transform(foo.begin(),                foo.end(),                std :: back_inserter(bar),                [this](float a){return this->function(a); }) - Justin Randall

0

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

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