简体   繁体   中英

Why did the C++ designers choose not to allow non-member operator()()?

I am just playing with std::function<> and operator s, to make C++ statements look like Functional Languages( F# ) and found out that there is a difference between operator() and operator<< . My code :

Function 1 (Operator Overload):

function<int(int)> operator>>(function<int(int)> f1, function<int(int)> f2)
{
  function<int(int)> f3 = [=](int x){return f1(f2(x));};
  return f3;
}

Function 2 (Operator Overload):

function<int(int, int)> operator>>(function<int(int, int)> f1, function<int(int)> f2)
{
  function<int(int, int)> f3 = [=](int x,int y){return f2(f1(x, y));};
  return f3;
}

Function 3 (Operator Overload):

function<int(int)> operator()(function<int(int, int)> f1, int x)
{
  function<int(int)> f2 = [=](int y){return f1(x, y);};
  return f2;
}

while the Function 1 and Function 2 ( or Operator Overload ), Function 3 gives out error that :

error: ‘std::function<int(int)> operator()(std::function<int(int, int)>, int)’ must be a nonstatic member function
     function<int(int)> operator()(function<int(int, int)> f1, int x)
                                                                    ^

Why do operator() needs to be non-static member? I think its different than What is the difference between the dot (.) operator and -> in C++? In that question the answer is explained in terms of pointers. But here I am using simple operator() and operator>> , which has nothing to do with pointers.

Those are the rules that the language designers decided on. operator() allows for a syntax which looks like it is part of the class itself ( std::function in your case) and the interface of that class should be controlled by the class itself.

The standard defines this in

13.5.4 Function call [over.call]

1 operator() shall be a non-static member function with an arbitrary number of parameters. [...]

emphasis mine

Similar decisions were made for other operators like assignment = , subscripting [] and class member access -> , while for operators like >> , they decided that it makes sense to allow adding operators between two (almost) arbitrary classes independently of the class' interface itself.

operator>>() can be called as a non-static member or as a standalone function, depending on how it is defined for the left-hand data type. The statement:

lhs >> rhs

Can resolve as either:

lhs.operator>>(rhs) // non-static member

Or:

operator>>(lhs, rhs) // standalone function

operator() , on the other hand, cannot be called as a standalone function. It must have something on the left-hand side to invoke it. The statement:

lhs(arguments)

Can only resolve as:

lhs(arguments) // only if lhs is an actual function

Or:

lhs.operator()(arguments) // must be a non-static member

There is no C++ language syntax that would allow the statement:

lhs(arguments)

to resolve as:

operator()(lhs, arguments)

operator>>() can be overloaded as a non-member function but not operator() . operator() can only be a non-static member function of a class or a struct .

From the standard:

13.5.4 Function call [over.call]

1 operator() shall be a non-static member function with an arbitrary number of parameters. It can have default arguments. It implements the function call syntax

postfix-expression ( expression-list opt )

where the postfix-expression evaluates to a class object and the possibly empty expression-list matches the parameter list of an operator() member function of the class. Thus, a call x(arg1,...) is interpreted as x.operator()(arg1, ...) for a class object x of type T if T::operator()(T1, T2, T3) exists and if the operator is selected as the best match function by the overload resolution mechanism (13.3.3).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM