Why can't operator () of stateless functor be static?

Per standard 13.5/6,

An operator function shall either be a non-static member function or be a non-member function and have at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.

Additionally, in 13.5.4 it is stated that

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


I would think that there's no technical reason to forbid this (but not being familiar with the de-facto cross-vendor C++ ABI (Itanium ABI), I can't promise anything).

There's however an evolutional issue about this at https://cplusplus.github.io/EWG/ewg-active.html#88 . It even has the [tiny] mark on it, making it a somewhat "trivial" feature under consideration.


I can't see any technical reason to forbid a static auto operator()( ... ). But it's a special case, so it would complicate the standard to add support for it. And such complication is not necessary, because it's very easy to emulate:

struct L
{
    static void func() {}

    void operator()() const { func(); }

    operator auto () const
    { 
        return &L::func;
    }
};

See Johannes' answer for some possibly useful extra info.


Like the others, I don't see a fundamental reason why it is not possible to have a static operator(), for stateless functors or in general.

(EDIT 2020: Just found this proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1169r0.html)

(UPDATE 2021: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1169r1.html)

In some cases might conflict, according to other rules, with member/static overloading which is not allowed in C++ (again, not sure why).

struct A{
  void f();
  static int f(); // compile error 
}

So even if it were allowed to have a static operator(), should this be permitted?

struct A{
  void operator()();
  static int operator()(); // should be a compiler error??? 
}

Anyway, there is only one true reason to have a static operator() that it is not purely a syntactic reason and it is that objects should be able to call static functions as if they were member functions.

struct A{
   static int f():
}
...
A a; 
a.f(); // calls A::f() !!!

Specifically, the user of the class A doesn't need to know if a function is implemented as static or as a member. It can later be upgraded to a member function from a generic point of view.

Leaving that important application to generic programming aside, there is a workaround the leads to a similar syntax that I saw in https://quuxplusone.github.io/blog/2018/03/19/customization-points-for-functions/, and that is to have a static member function called _, a name that doesn't imply any meaning.

struct A{
    static int _();
}
...
A::_(); // instead of the more desirable (?) A::() or A::operator()
a._(); // this invokes the static functon _ 

Instead of the more desirable A::() or A::operator(), (well are they desirable at all? I don't know; something like A() would be really interesting but doens't even follow the syntax of a static function and can be confused with a constructor).

(As I said, the only feature I still miss, regarding this limitation you point out, is that a() cannot automatically delegate to a static version of the operator(), e.g. A::operator().)

In summary, your code could look like this:

struct L{
    static void _() {} 
    auto operator()() const{ 
        return L::_();
    }
};

L ell; 
ell(); // calls L::_() really.

Not sure what are willing to achieve still.


One can "CRTP" the idea https://godbolt.org/z/74vxsTYxd

#include<utility> // forward

template<class Self>
struct stateless_functor_facade{
    template<class... Args>
    constexpr decltype(auto) operator()(Args&&... args) const{
        return Self::operator_paren(std::forward<Args>(args)...);
    }
};

struct square : stateless_functor_facade<square>{
    static auto operator_paren(double x){return x*x;}
};

int main(){
    square s;
    s(5);
}