【问题标题】:Declaring member function using function type syntax使用函数类型语法声明成员函数
【发布时间】:2017-12-17 21:27:46
【问题描述】:

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

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;
};

在上面的代码中

  • fun_global 是一个全局函数,
  • mem_fun_staticstatic 成员函数,
  • mem_fun_normal是一个普通的方法,
  • mem_fun_virtual 是一个virtual 方法,
  • mem_fun_abstract 是一个抽象方法。

它们都采用 double 类型的单个参数并返回 int 值 - 就像 function_type 所说的那样。

这些年来我都知道 C++,但我对此一无所知 - 这种语言从未停止让我感到惊讶!顺便说一句-here 的任何地方都提到过这种语法吗?我没看到这个...

但是,在探索这个新功能时,我偶然发现了编译器之间的一些不一致。对于测试,我使用了以下编译器:

  • 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;
};
  • 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.
    
  • MSVC:好的

= default 不一致

struct methods
{
    /* ... */
    using assignment_type = methods& (methods const&);
    assignment_type operator= = default;
};
  • GCC:好的
  • Clang:错误!

    Test.cpp:14:30: error: '= default' is a function definition and must occur in a standalone declaration
            assignment_type operator= = default;
                                        ^
    1 error generated.
    
  • MSVC:错误!

    Test.cpp(14): error C2206: 'methods::operator =': typedef cannot be used for function definition
    

内联定义不一致

struct methods
{
    /* ... */
    function_type mem_fun_inline { return 0; }
};
  • 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
    
  • 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.
    
  • MSVC:好的


问题

这里有哪些编译器?

此外,是否有可能:

  1. 在内联定义中(仅受 MSVC 支持)以某种方式引用参数?
  2. 不知何故在这些函数的定义中使用function_type(当在类之外完成时)。以下是可以的(所有编译器)

    struct methods
    {
        static function_type mem_fun_static;
        /* ... */
    };
    
    int methods::mem_fun_static(double) { return 0; }
    

    这并没有那么糟糕,因为function_type 的更改应该会导致函数定义处的编译错误(因为它将不再匹配声明) - 但仍然有可能避免这种情况。

【问题讨论】:

  • 好问题!意识到这一点,但除了指定预期回调函数的类型(主要是在 C 代码中也是如此)之外,几乎没有什么实际用途。
  • @StoryTeller 实际上我就是这样发现的! - 使用我们拥有的框架的“线程主”回调。
  • 令人惊讶的是,这些函数的前向声明如何变得不言自明,不是吗?我也喜欢指针语义没有隐藏在别名后面。
  • 顺便说一句,它也可以用作std::function 的类型参数。同样,更多的自我记录代码。
  • @AdamBadura 这可能不是你的错!我有时发现谷歌搜索 foo bar stackoverflow 产生的结果比 SO 自己的重复查找器更有用,这很不幸,但仍然是一个方便的备份。

标签: c++ g++ clang++ cl


【解决方案1】:

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

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

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

【讨论】:

  • 你引用的是什么版本?您能否也添加部分名称? (章节名称在不同版本中是稳定的,数量不是很多)。
  • 我很惊讶= delete 算作函数​​定义。如果您也可以提供报价,那就更好了。但你的回答回答了一切,所以谢谢!
  • @AdamBadura 8.4.3 [dcl.fct.def.delete] “形式为 ... 的函数定义称为已删除定义”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2012-08-04
  • 1970-01-01
  • 1970-01-01
  • 2017-12-08
相关资源
最近更新 更多