function object

Generically, function objects are instances of a class with member functionoperator() defined. This member function allows the object to be used with the same syntax as a regular function call, and therefore its type can be used as template parameter when a generic function type is expected.

#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

template<class T>
class CSum {
private:
    T sum;
public:
    CSum() { sum = 0; }

    void operator()(T n){
        sum += n;
    }

    T GetSum() {
        return sum;
    }
};

int main(){
    vector<int> v;
    for (int i=0; i<=100; i++){
        v.push_back(i);
    }

    CSum<int> o = for_each(v.begin(), v.end(), CSum<int>());
    cout << o.GetSum() << endl;

    return 0;
}
The function object sum all the numbers in a vector.

1. function object overload operator().

2. in the for_each, call the function object by its constructor.

3. CSum<int> o  receives final result.

A good review is here and here.

We could also inherint from unary_function class

#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

template <class inputPar, class outPar>
class CSum : public unary_function<inputPar, outPar> {
private:
    outPar sum;
public:
    CSum() { sum = 0; }
    void operator()(inputPar n){
        sum += n;
    }
    outPar getSum() { return sum; }
};

int main(){
    double temp;

    vector<int> v1;
    for(int i=1; i<=100; i++){
        v1.push_back(i);
    }

    vector<double> v2;
    for(int i=1; i<=100; i++){
        temp = i/100.0;
        v2.push_back(temp);
    }

    CSum<int, int> s1 = for_each(v1.begin(), v1.end(), CSum<int, int>());
    CSum<double, double> s2 = for_each(v2.begin(), v2.end(), CSum<double, double>());

    cout << s1.getSum() << endl;
    cout << s2.getSum() << endl;

    return 0;
}

Let us look binary_function. We first define a student class, contains student name and grade, then sort the student vector.

#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

class Student {
public:
    string name;
    int grade;

    Student(string name, int grade){
        this->name = name;
        this->grade = grade;
    }

    bool operator<(const Student &s) const {
        return grade < s.grade;
    }

    void printInfor(){
        cout << name << "\t" << grade << endl;
    }
};

template <class inPar1, class inPar2>
class binary_sort : public binary_function<inPar1, inPar2, bool>{
public:
    bool operator()(inPar1 s1, inPar2 s2){
        return s1 < s2;
    }
};

int main(){
    Student s1("Sam", 60);
    Student s2("Tom", 49);
    Student s3("Jim", 71);
    Student s4("David", 30);

    vector<Student> v;
    v.push_back(s1);
    v.push_back(s2);
    v.push_back(s3);
    v.push_back(s4);

    sort(v.begin(), v.end(), binary_sort<const Student &, const Student &>());

    vector<Student>::iterator itr = v.begin();
    while (itr != v.end()){
        itr->printInfor();
        itr++;
    }

    return 0;
}

stl has some build-in function objects

#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

int main (){
    /* create an object, and use the functions */
    plus<int> oplus;
    minus<int> ominus;
    multiplies<int> omultiple;
    divides<int> odivides;
    modulus<int> omodulus;
    negate<int> onegate;

    cout << oplus(2,4) << endl;
    cout << ominus(4,2) << endl;
    cout << omultiple(4,2) << endl;
    cout << odivides(4,2) << endl;
    cout << omodulus(4,2) << endl;
    cout << onegate(4) << endl;

    /* use a temporary object, call the operator */
    cout << plus<int>()(2,4) << endl;
    cout << minus<int>()(4,2) << endl;
    cout << multiplies<int>()(4,2) << endl;
    cout << divides<int>()(4,2) << endl;
    cout << modulus<int>()(4,2) << endl;
    cout << negate<int>()(4) << endl;

    return 0;
}

For simple build-in data type, we could directly use these function objects. But for complex data structure, we need to overload such operators within class. STL has complex number, here just an illustration.

#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

class Complex {
public:
    double real;
    double image;

    Complex():real(0.0),image(0.0){}
    Complex(double real_, double image_):real(real_),image(image_){}

    Complex operator+(const Complex& c) const {
        Complex v;
        v.real = real + c.real;
        v.image = image + c.image;
        return v;
    }

    void print(){
        cout << real << "+" << image << "i" << endl;
    }
};

int main(){
    Complex c1(3, 4.5);
    Complex c2(3.5, 4);
    Complex c3 = c1 + c2;
    Complex c4 = plus<Complex>()(c1, c2);

    c3.print();
    c4.print();

    cout << equal_to<Complex>()(c3, c4) << endl;
    cout << equal_to<Complex>()(c1, c2) << endl;

    Complex c;
    vector<Complex> v;
    v.push_back(c1);
    v.push_back(c2);
    v.push_back(c3);
    v.push_back(c4);

    Complex result = accumulate(v.begin(), v.end(), c, plus<Complex>());
    result.print();
}

Besides simple unary_function and binary_function base classes, we also have function adapters.

1. bind2nd(function, value);

2. bind1nd(function, value);

3. not1(function);

4. not2(function);

bind2nd takes a binary_function as a parameter, and fix its second parameter to value.

bind1nd takes a binary_function as a parameter, and fix its first parameter to value.

not1 takes an unary_function as input, and logically reverse its result.

not2 takes a binary_function as input, and logically reverse its result.

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    for(int i=0; i<10; i++){
        v.push_back(i+1);
    }

    vector<int>::iterator itr = v.begin();
    while (itr!=v.end()){
        cout << *itr << endl;
        itr++;
    }

    int ncout = count_if(v.begin(), v.end(), bind2nd(less<int>(), 4));
    cout << ncout << endl;

    return 0;
}
This example first construct a vector, and see whether its element is less than 4, count the number.
bind2nd(less<int>(), 4)
use less<int>() function, it is a binary_function, however, we use adapter to fix it second parameter to 4, so we could use it as an unary_function.

Above is for the build-in function, could we use class member function? Sure, we usemem_fun_ref andmem_fun. mem_fun_ref is applied for objects, mem_fun is applied to pointers to objects.

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

class Student{
public:
    string strNO;
    string strName;

    Student(string strNO_, string strName_):strNO(strNO_), strName(strName_){}
    void printInfo(){
        cout << strNO << ":" << strName << endl;
    }
};

int main(){
    Student s1("200001", "Tim");
    Student s2("200002", "Tony");
    Student s3("200003", "David");
    vector<Student> v;
    v.push_back(s1);
    v.push_back(s2);
    v.push_back(s3);
    for_each(v.begin(), v.end(), mem_fun_ref(&Student::printInfo));

    Student* ps1 = new Student("200001", "Tim");
    Student* ps2 = new Student("200002", "Tony");
    Student* ps3 = new Student("200003", "David");
    vector<Student*> pv;
    pv.push_back(ps1);
    pv.push_back(ps2);
    pv.push_back(ps3);
    for_each(pv.begin(), pv.end(), mem_fun(&Student::printInfo));

    return 0;
}

We can also use ordinary function via ptr_fun adapter.

#include <functional>
#include <vector>

using namespace std;

bool g(int x, int y){
    return x > y;
}

int main(){
    vector<int> v;

    for(int i=0; i<10; i++){
        v.push_back(i+1);
    }
    vector<int>::iterator itr = v.begin();
    while(itr!=v.end()){
        cout << *itr << endl;
        itr++;
    }

    int ncout = count_if(v.begin(), v.end(), bind2nd(ptr_fun(g), 5));
    cout << ncout << endl;
}

Some applications

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

class Shape{
public:
    virtual void calArea() = 0;
};

class Circle : public Shape{
public:
    Circle(double r_):r(r_){}
    virtual void calArea(){
        cout << 3.14*r*r << endl;
    }
private:
    double r;
};

class Rectangle : public Shape{
public:
    Rectangle(double width_, double height_):width(width_), height(height_){}
    virtual void calArea(){
        cout << width*height << endl;
    }
private:
    double width, height;
};

int main(){
    Circle* s1 = new Circle(0.5);
    Rectangle* s2 = new Rectangle(2, 0.4);

    vector<Shape*> v;
    v.push_back(s1);
    v.push_back(s2);

    for_each(v.begin(), v.end(), mem_fun(&Shape::calArea));

    return 0;
}
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;

class Student{
public:
    string strNO;
    double Grade;

    Student(string strNO_, double Grade_):strNO(strNO_), Grade(Grade_){}
};

template <class T>
class StudentIndex : public binary_function<T, T, bool>{
private:
    vector<Student>&v;
public:
    StudentIndex(vector<Student>&v_):v(v_){}
    bool operator()(T a, T b){
        return v.at(a).Grade < v.at(b).Grade;
    }
};

int main(){
    Student s1("1001", 70);
    Student s2("1002", 60);
    Student s3("1003", 80);
    Student s4("1004", 74);
    vector<Student> v;
    v.push_back(s1);
    v.push_back(s2);
    v.push_back(s3);
    v.push_back(s4);

    vector<int>vIndex;
    vIndex.push_back(0);
    vIndex.push_back(1);
    vIndex.push_back(2);
    vIndex.push_back(3);

    sort(vIndex.begin(), vIndex.end(), StudentIndex<int>(v));
    vector<int>::iterator itr=vIndex.begin();
    while(itr!=vIndex.end()){
        cout << *itr << endl;
        itr++;
    }


    return 0;
}



### 回答1: riptable 这个错误提示通常出现在JavaScript中,意思是“函数对象不可订阅”。它通常出现在你试图访问一个函数对象的属性或方法时,但该函数对象并没有这个属性或方法。可能是因为你的代码中有拼写错误或逻辑错误,导致函数对象没有正确定义。建议检查代码中的拼写和逻辑错误,确保函数对象被正确定义。 ### 回答2: "function object is not subsc" 这个错误信息通常是在使用函数对象时出现的。它的意思是函数对象不支持直接通过下标来访问其元素。 在Python中,函数也被视为对象,可以像其他对象一样进行操作。但是,与列表或字典等对象不同,函数对象并不支持通过下标来访问其元素,因为函数对象没有内置的索引机制。 如果你尝试通过下标访问函数对象,Python解释器会抛出"function object is not subsc"这个错误。例如,如果你尝试像下面这样访问函数对象的某个元素: ```python def my_function(): ... print(my_function[0]) # 这里会抛出"function object is not subsc"错误 ``` 为了解决这个问题,你可以使用函数对象的其他属性和方法来操作它。例如,你可以直接调用函数对象以执行函数的操作,例如: ```python def my_function(): ... result = my_function() # 调用函数对象执行函数操作 ``` 另外,你还可以使用内置的函数`dir()`来查看函数对象的所有属性和方法。例如: ```python def my_function(): ... print(dir(my_function)) # 打印函数对象的所有属性和方法 ``` 总之,"function object is not subsc"错误的意思是函数对象不支持通过下标直接访问其元素,你需要使用其他合适的方法来操作函数对象。 ### 回答3: "function object is not subscriptable"这个错误信息通常出现在尝试对一个函数对象进行下标操作时。函数对象是不可迭代的,它的本质是一个可调用的对象,并不是一个包含元素的容器。 当我们使用下标操作符[]来访问一个对象时,Python会尝试在该对象上调用__getitem__()方法来获取指定下标位置的元素。然而,对于函数对象而言,并没有实现__getitem__()方法,因此会引发"function object is not subscriptable"错误。 要解决这个问题,我们需要检查代码中是否存在对函数对象的不正确使用。如果我们需要在函数调用时传递参数,可以直接使用函数名加括号的方式进行调用,而不是使用下标操作符。例如,正确的调用一个函数可以这样做:function_name()。 此外,也要确保我们不会错误地把函数当作一个包含元素的列表或字典来使用。如果我们需要存储和处理多个函数对象,可以考虑使用列表或字典来保存这些函数,并使用合适的索引或键来访问相应的函数。例如,可以使用function_list[0]()来调用列表中的第一个函数。 总之,"function object is not subscriptable"错误提醒我们不能对函数对象使用下标操作符[],而应该使用正确的函数调用方式来执行函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值