带有尾随 return 类型的 c++11 typedef 函数指针

c++11 typedef function pointer with trailing return type

我一直在尝试清理继承的代码库。它广泛使用了包含尾随 return 类型的模板函数。它还包括许多指向非模板化、非成员函数的函数指针。在清理过程中,我发现在 Visual Studio 2013:

下,等效于以下工作的代码
#define function typedef auto

function Kernel (int, int) -> int;

struct Transform
{
    Kernel* kernel;
    char*   description;
};

Transform add_transform { add, "add" };

这个 typedef 在 C++11 标准中有效吗?

虽然我个人像瘟疫一样避免使用#defines(尤其是当用于创建像这些 'functions' 这样的新语言功能时),但考虑到项目中尾随 return 类型的普遍存在,团队认为这将使代码库更具可读性。

尾部 return 类型语法是 C++11 中的新语法,它在任何可以编写函数类型的地方都有效。 auto <function>(<parameters>) -> <result> 只是一种奇特的写法 <result> <function>(<parameters>)(好处是 <result> 可以引用 <parameters>)。

这意味着 typedef auto Kernel (int, int) -> int; 完全有效,并且与 typedef int Kernel (int, int); 的含义完全相同。 Kernel typedef 可用于函数声明或函数指针声明。

使用宏重新发明 C++ 语法可能很诱人。你可能想出像这样很酷的东西,然后想 "wow that's so much more clear".

这种方法最根本的问题是它只对发明宏的人或对 C++ 不够了解的人更具可读性。如果您完全可以理解 typedef auto fn(int) -> int 的含义,那么您将不再发现您的宏有任何用处。语法已经很清楚了。

为了使事情复杂化,您引入了宏的所有无数问题。您正在全面劫持 function 符号名称 - 无论范围如何。现在您不能再使用 std::function。您不仅不能使用它,而且还会抛出一些令人讨厌的编译器错误,这些错误根本不是描述性的。编译器将尝试解析 std::typedef auto 这是无稽之谈。

它是有效的,因为 auto(int, int) -> int; 是一个函数声明符,只是它缺少名称。名称 Kerneltypedef 说明符用来创建 type-name 的标识符。由于 trailing-return-type 存在,autoint 取代,变成 int(int, int)。如果您想说服您的团队这是徒劳的,请考虑实现相同语法的方法:

using Kernel = int(int, int);
using Kernel = auto(int, int) -> int;
typedef auto Kernel(int, int) -> int;

这些在语义上都是等价的,并且避免使用宏。