为什么我不能将函数中定义的函子传递给另一个函数?

时间:2014-02-15 06:35:54

标签: c++

我发现仿函数可以用来模拟在像这样的函数中定义一个函数

using namespace std;
int main(int argc, char* argv[])
{
    struct MYINC {
        int operator()(int a) { return a+1; }
    } myinc;
    vector<int> vec;
    for (int i = 0; i < 10; i++) vec.push_back(myinc(i));
    return 0;
}

但是,如果我将它传递给外部函数,例如 std :: transform ,如下例所示,我有一个编译错误,说error: no matching function for call to ‘transform(std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator, main(int, char**)::MYINC&)’

using namespace std;
int main(int argc, char* argv[])
{
    struct MYINC{
        int operator()(int a) { return a+1; }
    } myinc;
    vector<int> vec;
    for (int i = 0; i < 10; i++) vec.push_back(i);
    transform(vec.begin(), vec.end(), vec.begin(), myinc);
    return 0;
}

所以我把这个定义放在 main 函数之外,现在一切正常。

using namespace std;
struct MYINC{
    int operator()(int a) { return a+1; }
} myinc;
int main(int argc, char* argv[])
{
    vector<int> vec;
    for (int i = 0; i < 10; i++) vec.push_back(i);
    transform(vec.begin(), vec.end(), vec.begin(), myinc);
    return 0;
}

2 个答案:

答案 0 :(得分:6)

两个版本都可以使用g ++ 4.8.2编译,这是一个C ++ 11编译器。

然而,C ++ 03编译器不会实例化具有本地类型的模板,因为在C ++ 03中不支持。

一个解决方案,如果这确实是问题的根本原因,那么就是使用更新的编译器版本或其他编译器。

另一种解决方案是利用它,即使在C ++ 03中,您也可以在本地定义“真实”函数,方法是将其作为本地类的 static 成员函数(在C ++ 11中也可以通过使用lambda表达式来实现。)

然而,除了处理这样的问题之外,仿函数与“真实”函数相比具有一般的性能优势,即具有类的对象而不仅仅是函数指针,以及相关的{{1}作为operator(),编译器可以更好地优化,因为它知道函数实现。

答案 1 :(得分:1)

由于我不完全清楚的原因,在C ++ 03中有一个众所周知且非常恼人的限制,您可以使用它来实例化模板。

本地定义的类不能用作模板的参数,只是因为。

顺便说一下,对<algorithm>库的使用非常困难,因为你无法将代码的上下文保持在本地,而是强制将所有函子,比较器等放在命名空间级别为他们制作有趣的名字,并将它们放在远离使用点的地方。