为什么stateless functor的operator()不能是static的?

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

为什么stateless functor的operator ()不允许是static?无状态 lambda 对象可转换为指向具有与其 operator ().

相同签名的自由函数的指针

Stephan T. Lavavej 第6 指出转换为函数指针 只是一个 operator FunctionPointer() (引用)。但是对于非成员函数,我无法获得指向 operator () 的相应指针。对于函子 struct F { void operator () () {} } 似乎不可能将 &F::operator () 转换为 using P = void (*)();.

类型的实例

代码:

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

错误是

overloaded 'operator()' cannot be a static member function

但是 operator () 没有超载。

按照标准 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.

此外,在 13.5.4 中声明

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

我认为没有技术理由禁止这样做(但不熟悉事实上的跨供应商 C++ ABI (Itanium ABI),我不能保证任何事情)。

但是 https://cplusplus.github.io/EWG/ewg-active.html#88 上有一个关于此的进化问题。它甚至有 [tiny] 标记,使其成为考虑中的 "trivial" 功能。

在相关 委员会 考虑这个微不足道的功能之前,一个简单的、有点肮脏的解决方法:

Glob 运算符在语法上与构造函数相似。

因此,你不能写

static MyClass::operator()(...);

这简直是不可能的,因为 委员会 出于不明确的原因做出了这样的决定。如果我能与他们的一位成员交谈,询问他们在做出决定时的想法,我会很高兴。不幸的是,他可能不会理解我的问题,因为他从未编写过 C++ 程序。他只处理它的文档。

现在他们需要几十年

  • 辩论
  • 协商
  • 会议
  • 和注意事项

实现一个微不足道的功能。我怀疑该功能可能在 c++3x 中可用,甚至可以在仿真机器上试用它。

在那之前,你可以尝试写:

MyClass::MyClass(...);

在这两种情况下,您都可以调用 MyClass(...);

当然有用主要是MyClass是单例。而且,我会说这是一个黑客。此外,它在堆栈上分配了一个sizeof(MyClass),这在性能/效率方面可能很糟糕。


此外,这本质上是一个构造函数,而构造函数不能return任何东西。但是您可以通过将结果存储在实例中,然后通过转换运算符将其转换为您希望的任何内容来避免这种情况。

我看不出任何禁止 static auto operator()( ... ) 的技术理由。但这是一个特例,因此增加对它的支持会使标准复杂化。而这样的复杂化是没有必要的,因为它很容易模仿:

struct L
{
    static void func() {}

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

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

有关一些可能有用的额外信息,请参阅

像其他人一样,我没有看到为什么不可能有静态 operator()、无状态仿函数或 一般 的根本原因。

(2020 年编辑:刚找到这个提案 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1169r0.html

(2021 年更新:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1169r1.html

在某些情况下,根据其他规则,可能会与 member/static 重载发生冲突,这在 C++ 中是不允许的(同样,不确定为什么)。

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

所以即使它被允许有一个 static operator(),这应该被允许吗?

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

无论如何,只有一个 static operator() 的真正原因,它不是纯粹的语法原因,而是对象应该能够调用静态函数,就好像它们是成员函数一样。

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

具体来说,class A 的用户不需要知道函数是作为静态函数还是作为成员实现的。 以后可以从泛型的角度升级为成员函数。

撇开泛型编程的重要应用不谈,有一个解决方法导致我在 https://quuxplusone.github.io/blog/2018/03/19/customization-points-for-functions/ 中看到的类似 语法 ,那就是有一个名为 _ 的静态成员函数,一个没有任何含义的名称。

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

而不是更令人向往的 A::()A::operator(),(它们真的很令人向往吗?我不知道;像 A() 这样的东西会很有趣,但确实如此它甚至不遵循静态函数的语法,可能会与构造函数混淆)。

(正如我所说,关于您指出的这个限制,我仍然怀念的唯一功能是 a() 无法自动委托给 operator() 的静态版本,例如 A::operator().)

总而言之,您的代码可能如下所示:

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

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

还不确定要实现什么。


一个可以“CRTP”的想法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);
}

我根本不会假装自己是专家。但是,我正在研究 static lamdas 或 static operator() 以及他们正在进行的关于它的提案。我对我能理解的内容感到满意。

看来提出的想法正在努力解决如何设计它而不破坏其他 code.etc。然而,他们似乎正在研究解决方案。所以。也许有一天!

static operator() 
Document #: P1169R2  
Date:   2021-08-14
Project: Programming Language C++

3 Proposal

The proposal is to just allow the ability to make the call operator a static member function, instead of requiring it to be a non-static member function. We have many years of experience with member-less function objects being useful. Let’s remove the unnecessary object parameter overhead. There does not seem to be any value provided by this restriction.

There are other operators that are currently required to be implemented as non-static member functions - all the unary operators, assignment, subscripting, conversion functions, and class member access. We do not believe that being able to declare any of these as static will have as much value, so we are not pursuing those at this time. We’re not aware of any use-case for making any of these other operators static, while the use-case of having stateless function objects is extremely common.

在此处查找完整文档:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1169r2.html