使用函数类型语法声明成员函数

Ada*_*ura 10 c++ g++ clang++ cl

就在最近,我了解到你可以使用类似函数类型的变量语法来声明一个函数(包括方法):

using function_type = int (double);
// pre-C++11:
//typedef int function_type(double);

function_type fun_global;

struct methods
{
    static function_type mem_fun_static;
    function_type mem_fun_normal;
    virtual function_type mem_fun_virtual;
    virtual function_type mem_fun_abstract = 0;
};
Run Code Online (Sandbox Code Playgroud)

在上面的代码中

  • fun_global 是一个全球性的功能,
  • mem_fun_static是一个static成员函数,
  • mem_fun_normal 是一种普通的方法,
  • mem_fun_virtual是一种virtual方法,
  • mem_fun_abstract 是一种抽象的方法.

所有这些都采用单一的类型参数double和返回int值 - 就像function_type说的那样.

这些年来我都知道C++而且我不知道这个 - 这种语言永远不会让我感到惊讶!顺便说一下 - 这里提到的语法是什么?我没看到这个......

然而,在探索这个新功能时,我偶然发现编译器之间存在一些不一致之处.对于测试,我使用以下编译器:

  • GCC 5.4.0和7.1.0,命令行: g++ -Wall -Wextra -pedantic -std=c++14
  • Clang 4.0.1,命令行: clang++ -Wall -Wextra -pedantic -std=c++14
  • MSVC 19.10.25019(VS 2017),命令行: cl /W4 /EHsc

在我运行的测试中,两个GCC版本都给出了相同的结果,因此我将它们称为GCC.


= delete 前后矛盾

struct methods
{
    /* ... */
    function_type mem_fun_deleted = delete;
};
Run Code Online (Sandbox Code Playgroud)
  • GCC:好的
  • Clang:错误!

    Test.cpp:13:34: error: '= delete' is a function definition and must occur in a standalone declaration
            function_type mem_fun_deleted = delete;
                                            ^
    1 error generated.
    
    Run Code Online (Sandbox Code Playgroud)
  • MSVC:好的

= default 前后矛盾

struct methods
{
    /* ... */
    using assignment_type = methods& (methods const&);
    assignment_type operator= = default;
};
Run Code Online (Sandbox Code Playgroud)

内联定义不一致

struct methods
{
    /* ... */
    function_type mem_fun_inline { return 0; }
};
Run Code Online (Sandbox Code Playgroud)
  • GCC:错误!

    Test.cpp:13:43: error: invalid initializer for member function ‘int methods::mem_fun_inline(double)’
      function_type mem_fun_inline { return 0; }
                                               ^
    Test.cpp:13:43: error: expected ‘;’ at end of member declaration
    
    Run Code Online (Sandbox Code Playgroud)
  • Clang:错误!

    Test.cpp:13:33: error: expected expression
            function_type mem_fun_inline { return 0; }
                                           ^
    Test.cpp:7:8: error: missing '}' at end of definition of 'methods'
    struct methods
           ^
    /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/x86_64-pc-cygwin/bits/c++config.h:194:1: note: still within definition of 'methods' here
    namespace std
    ^
    2 errors generated.
    
    Run Code Online (Sandbox Code Playgroud)
  • MSVC:好的


问题

哪些编译器就在这里?

此外,是否有可能:

  1. 在内联定义(仅由MSVC支持)以某种方式引用参数?
  2. 以某种方式使用function_type也定义了那些函数(当在类之外完成时).以下是好的(所有编译器)

    struct methods
    {
        static function_type mem_fun_static;
        /* ... */
    };
    
    int methods::mem_fun_static(double) { return 0; }
    
    Run Code Online (Sandbox Code Playgroud)

    它并没有那么糟糕,因为更改function_type应该导致函数定义中的编译错误(因为它将不再匹配声明) - 但仍然可能甚至可以避免.

n. *_* m. 4

\n

\xc2\xa7 8.3.5 函数 [dcl.fct] p12 函数类型的 typedef 可用于声明函数,但不得用于定义函数。

\n
\n\n

因此,Clang 在所有情况下拒绝代码都是正确的,而接受它的编译器是错误的。

\n\n

(引文来自 N4618,但该规则永远是该语言的一部分)。

\n

  • @AdamBadura 8.4.3 \[dcl.fct.def.delete\] “...形式的函数定义称为删除定义”。 (3认同)
  • 您引用的是什么修订版?您能否也添加部分名称?(章节名称在各个版本中都很稳定,数量则不太稳定)。 (2认同)