为什么无状态函子的operator()是静态的?

时间:2015-09-25 06:53:01

标签: c++ lambda function-pointers c++14 functor

为什么无状态仿函数operator ()不允许static?无状态lambda对象可转换为指向与operator ()具有相同签名的自由函数的指针。

第p页的{p> 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 ();
    }
};

错误是

  

重载'运营商()'不能是静态成员函数

operator ()没有超载。

5 个答案:

答案 0 :(得分:12)

按照标准13.5 / 6,

  

运算符函数应该是非静态成员函数或者是非成员函数并且具有   至少一个参数,其类型是类,对类的引用,枚举或对引用的引用   枚举。

此外,在13.5.4中声明

  

运算符()   应该是具有任意数量参数的非静态成员函数。它可以有   默认参数。它实现了函数调用语法   后缀表达式   (   表达式列表   选择   )   在哪里   后缀表达式   求值为一个类对象,可能为空   表达式列表   火柴   一个参数列表   运算符()   该类的成员函数。因此,一个电话   X(ARG1,...)   被解释   如   x.operator()(arg1,...)   对于一个类对象   X   类型   Ť

答案 1 :(得分:5)

我认为没有技术理由禁止这一点(但不熟悉事实上的跨厂商C ++ ABI(Itanium ABI),我不能承诺任何事情)。

然而https://cplusplus.github.io/EWG/ewg-active.html#88有一个关于这个问题的进化问题。它甚至还有 [tiny] 标记,使其成为一个有点“微不足道”的特征。

答案 2 :(得分:5)

我无法看到禁止static auto operator()( ... )的任何技术原因。但这是一个特殊情况,因此它会使标准复杂化以增加对它的支持。而且这种复杂性并不是必需的,因为它很容易模仿:

struct L
{
    static void func() {}

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

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

请参阅Johannes' answer了解一些可能有用的额外信息。

答案 3 :(得分:1)

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

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

因此,你不能写一个

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

这根本不可能,因为委员会决定了不明原因。如果我可以和他们的一个成员交谈,问我们在他们的决定中是什么,我会很高兴。不幸的是,他可能不会理解我的问题,因为他从未编写过c ++程序。他只研究过它的文档。

现在他们需要几十年的时间

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

实现一个简单的功能。我怀疑该功能可以在c ++ 3x中使用,而在仿真机器上甚至可以尝试使用。

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

MyClass::MyClass(...);

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

当然,如果MyClass是单身,那么它很有用。而且,我会说这是一个黑客。此外,它在堆栈上分配sizeof(MyClass),这在性能/效率方面可能不好。

此外,这本质上是一个构造函数,构造函数不能返回任何东西。但是你可以通过将结果存储在实例中,然后通过强制转换操作符将其转换为你想要的任何东西来避免这种情况。

答案 4 :(得分:1)

像其他人一样,我看不出根本不可能的根本原因。

在某些情况下,根据其他规则,可能会与成员/静态重载发生冲突,这在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() !!!

具体地说,类A的用户不需要知道函数是作为静态实现还是作为成员实现。 以后可以从一般角度将其升级为成员函数。

除了将重要的应用程序用于通用编程之外,还有一种解决方法可以导致产生类似我在https://quuxplusone.github.io/blog/2018/03/19/customization-points-for-functions/中看到的语法,即具有一个名为{的静态成员函数。 {1}},这个名字并不意味着任何含义。

_

(而不是更理想的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()

不确定要实现什么目标。