带有尾部返回类型的c++11 typedef函数指针



我一直在尝试清理继承的代码库。它广泛使用了包含尾随返回类型的模板函数。它还包括许多指向非模板化、非成员函数的函数指针。在清理过程中,我发现了相当于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标准中有效吗?

虽然我个人避免像瘟疫一样使用#定义(尤其是在用于创建像这些"函数"这样的新语言功能时),但考虑到项目中尾随返回类型的普遍性,团队认为这将使代码库的可读性显著提高。

尾部返回类型语法在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++语法可能很诱人。你可能会想出这样很酷的东西,然后想"哇,这太清楚了"。

这种方法最根本的问题是,它只对发明宏的人更可读,或者如果你对C++不够了解的话。如果你完全理解typedef auto fn(int) -> int的含义,那么你将不再觉得你的宏有用。语法已经足够清晰了。

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

它是有效的,因为auto(int, int) -> int;是一个函数声明符,只是缺少一个名称。名称Kerneltypedef说明符用于创建类型名称的标识符。由于存在尾随返回类型autoint取代,它变成int(int, int)。如果你想让你的团队相信这是徒劳的,考虑一下你可以实现相同语法的方法:

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

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

最新更新