5

在 C++11 中,这两行是等价的。据我所知,第二种语法的优点是返回类型在类范围内。因此,您可以直接使用类的嵌套类型和decltype非静态成员的表达式。此外,函数名称排列得很好。

int foo(int bar);
auto foo(int bar) -> int;

这里auto使用了关键字,也可以用来自动推导局部变量的类型。但是,我看不到这里的类比。在函数声明语法中,没有派生任何内容。返回类型在箭头后面明确提到。

就个人而言,我会说如果没有auto关键字,语法会更清晰。这背后有什么意图吗?哪个?

4

2 回答 2

4

论文“Decltype (revision 5)”,N1978提出了trailing-return-type的语法(现在已知)。这样做是为了简化定义函数模板,其返回类型取决于第 3 章中涉及其参数的表达式:

template <class T, class U> decltype((*(T*)0)+(*(U*)0)) add(T t, U u);

该表达式(*(T*)0)是编写具有该类型T且不需要T默认可构造的表达式的一种骇人听闻的方式。如果参数名称在范围内,则上述声明可以写成:

template <class T, class U> decltype(t+u) add(T t, U u);

在 [Str02] 中讨论了将返回类型表达式移到参数列表之后的几种语法。如果返回类型表达式出现在参数列表之前,则解析变得困难并且名称查找可能不太直观;参数名称可能在函数声明位置的外部范围内有其他用途。

我们建议重用auto关键字来表示返回类型在参数列表之后。返回类型表达式以->符号开头,并在成员函数和异常规范中的参数列表和潜在的 cv 限定符之后:

template <class T, class U> auto add(T t, U u) -> decltype(t + u);

参考文献 [Str02] 是“Bjarne Stroustrup。“typeof”提案草案。C++ 反射器消息 c++std-ext-5364,2002 年 10 月。” ,但我不确定这是否公开。

于 2014-10-03T19:38:24.353 回答
0

添加此答案以补充@dyp 的出色答案。

这是我项目中一些代码的真实示例,如果没有尾随返回类型,将很难编写:

    template<class F, class... ArgTypes>
    auto expected_from_code(F&& f, ArgTypes&& ...args)
    -> expected_t<
    typename std::enable_if<
    !std::is_void<decltype(f(std::forward<ArgTypes>(args)...))>::value,
    decltype(f(std::forward<ArgTypes>(args)...))>::type>
    {
        using expected = expected_t<decltype(f(std::forward<ArgTypes>(args)...))>;
        try {
            return expected { f(std::forward<ArgTypes>(args)...) };
        }
        catch(...) {
            return expected { typename expected::exception_sentinel{} };
        }
    }
于 2014-10-03T19:47:23.887 回答