Function Call Operator and Overload, Type Conversion

Keywords: Lambda C++

Function call operator: operator()
Function operators must be member functions. A class can define multiple versions of call operators, which should differ from each other in the number or type of parameters. If a class defines a call operator, the object of that class is called a function object.
Function object classes can contain other members in addition to operator. These members are usually used to customize operations in call operators.

#include <iostream>
#include <string>
class A
{
public:
    int operator()(bool a,int b,int c) const
    {
        if(a)
            return b;
        else 
            return c;
    }
};
class GetInput
{
public:
    GetInput(std::istream &i=std::cin):is(i){}
    std::string operator()()const
    {
        std::string str;
        std::getline(is,str);
        return is?str:std::string();
    }
private:
    std::istream &is;
};
int main()
{
    A a;
    int ret=a(0,7,8);
    std::cout<<ret<<std::endl;
    GetInput gi;
    std::cout<<gi()<<std::endl;
    return 0;
}

The lambda expression is equivalent to an object whose class contains function callers.

stable_sort(words.begin(),words.end(),[](const string &a,const string &b){return a.size()<b.size()});
//Equivalent to
class shorterstring
{
public:
    bool operator()(const string &a,const string &b) const
    {
        return a.size()<b.size()
    }
}

The standard library defines a set of classes representing arithmetic operators, relational operators and logical operators. These classes are defined in the form of templates.

#include <iostream>
#include <functional>

int main()
{
    std::plus<int> intadd;
    int sum=intadd(10,20);
    std::cout<<sum;
    return 0;
} 

C++ language has several kinds of callable objects: functions, function pointers, lambda expressions, objects created by bind, classes of overloaded function operators. Different types may have the same form of invocation. When making function tables, we can use function templates to form function tables with different types and the same call form.

#include <functional>
#include <iostream>
#include <map>
#include <string>

int add(int i,int j){return i+j;}
auto mod=[](int i,int j){return i%j;}; 
struct Div{ int operator ()(int i, int j) const { return i / j; } };
auto binops=std::map<std::string,std::function<int(int,int)>>
{
    {"+",add},//Addition, function pointer 
    {"%",mod},//Remainder, named lambda object 
    {"/",Div()},//Division, Function Object Class 
    {"-" ,std::minus<int>()},//Subtraction, Standard Library Function Object 
    {"*",[](int i,int j){return i*j;}}//Multiplication, unnamed lambda objects 
};

int main()
{
    while ( std::cout << "Pls enter as: num operator num :\n", true )
    {
        int lhs, rhs; std::string op;
        std::cin >> lhs >> op >> rhs;
        std::cout << binops[op](lhs, rhs) << std::endl;
    }

    return 0;
}

Type conversion operator is a special member function of a class, which is responsible for converting the value of one class type into other types. A type conversion function must be a member function of a class, it cannot declare a return type, and the list of parameters must be empty. Class conversion type functions are usually const.

operator type() const;

Type conversion operators can produce unexpected results. The new C++11 standard introduces the type conversion operators displayed.

class SmallInt
{
    explicit operator int() const{return val;}
}
SmallInt si=3;//Correct
si+3;//Error. Implicit type conversion is required, but class operators are explicit
static_cast<int>(si)+3;//Correct: Explicitly requesting type conversion

Type conversion to bool is usually used in the conditional part, so operator bool is generally defined as explicit.

If a class contains one or more types, you must ensure that there is only one way to convert between the class type and the target type.
(1) Parametric matching and the same type conversion

struct B;
struct A
{
    A()=default;
    A(const B&);

};
struct B
{
    operator A() const; 
};
A f(const A&);
B b;
A a=f(b);//Ambiguity Error: f (B:: operator A ()? F (A:: A (const B &)
A a1=f(b.operator A());//Correct: Use B's type conversion operator
A a2=f(A(b));//Correct: Use the constructor of A

(2) Ambiguity and Multiple Type Conversion with Conversion Target as Built-in Type

Posted by timus on Fri, 22 Mar 2019 00:48:53 -0700