代码之家  ›  专栏  ›  技术社区  ›  George

C++ 14的后继返回类型语法的合法用法

  •  7
  • George  · 技术社区  · 7 年前

    是否有任何理由再使用以下语法:

    template<typename T>
    auto access(T& t, int i)
      -> decltype(t[i])
    {
        return t[i];
    }
    

    现在我们可以使用:

    template<typename T>
    decltype(auto) access(T& t, int i)
    {
        return t[i];
    }
    

    后面的返回类型语法现在看起来有点多余?

    2 回复  |  直到 7 年前
        1
  •  19
  •   Justin    7 年前

    导出的返回类型对SFINAE不友好。如果 t[i] 无效:

    template<typename T>
    auto access(T& t, int i)
      -> decltype(t[i])
    {
        return t[i];
    }
    

    然而,这种过载不会导致硬错误:

    template<typename T>
    decltype(auto) access(T& t, int i)
    {
        return t[i];
    }
    

    Demo


    std::optional<T> . 以下代码没有编译,因为 std::nullopt_t 与类型不同 标准::可选<T>

    #include <optional> // C++17 standard library feature
    
    template <typename T>
    auto foo(T const& val)
    {
        if (val.is_invalid()) return std::nullopt;
        return val.some_function_returning_an_optional();
    }
    

    尾部返回类型允许您精确指定要返回的表达式类型:

    template <typename T>
    auto foo(T const& val)
        -> decltype(val.some_function_returning_an_optional())
    {
        if (val.is_invalid()) return std::nullopt;
        return val.some_function_returning_an_optional();
    }
    

    std::declval ,这就更难理解了:

    template <typename T>
    decltype(std::declval<T const&>().some_function_returning_an_optional())
    foo(T const& val)
    {
        if (val.is_invalid()) return std::nullopt;
        return val.some_function_returning_an_optional();
    }
    

    Demo

        2
  •  7
  •   einpoklum    7 年前

    是的,至少有三个原因:

    1. 有意义的声明 :您的第一个变体具有 宣言 它告诉我返回类型是什么;您的第二个变体要求我读取您的 定义 . 但您的定义可能在另一个文件中,或者不太清楚。
    2. T[i] ,从而获得类型约束或从主体返回的内容到希望获得的内容的转换。
    3. 向后兼容性 这可能对你来说很微不足道,但是尝试写一个库,告诉你的用户“哦,你需要一个C++ 14兼容编译器,因为我的可爱的语法选择”。

    还有第四个原因 Justin's answer

    推荐文章