【问题标题】:Use of auto as return and parameters type in C++14在 C++14 中使用 auto 作为返回和参数类型
【发布时间】:2017-07-09 21:13:02
【问题描述】:

在 Bjarne Stroustrup 书(C++ 编程语言)的第 4 版中,我们读到:

使用 auto ,我们避免了冗余和编写长类型名称。这在泛型编程中尤其重要,因为程序员很难知道对象的确切类型并且类型名称可能很长(第 4.5.1 节)。

所以,要了解这种类型的重要性。我做了这个小测试程序:

#include <iostream>

/*-----------------------------*/
auto multiplication(auto a, auto b)
{
    return a * b;
}


int main()
{
  auto c = multiplication(5,.134);
  auto d = 5 * .134;
  std::cout<<c<<"\n"<<d<<"\n";

}

这个程序的标准输出(使用-std=C++14编译):

0
0.67

我想知道为什么即使乘法函数的返回类型是自动,我的 c 和 d 变量也会得到不同的结果(类型)。

编辑: 我的 GCC 版本:gcc version 5.4.0 20160609

【问题讨论】:

  • 这是一个非标准的扩展。 C++14 不允许函数使用 auto 参数。
  • 如果您将代码更改为实际合法的 C++14,您将获得预期的结果。 wandbox.org/permlink/eTZilBZhK19NOkDw
  • 我建议使用标志-pedantic-errors 进行编译以强制执行标准合规性。
  • 这给出了 gcc-5 的奇怪结果,但是 gcc-6 及更高版本的预期结果,所以错误并且已经修复。
  • @MohamedAmjadLASRI 是的,因为在参数中使用 auto 是非标准的。它不适用于其他编译器

标签: c++ c++14


【解决方案1】:

首先,您的代码使用gcc extension,即自动函数参数

我猜你的 gcc 版本不能正常使用扩展并提供不正确的结果(使用 gcc 7.1 我有 0.67 0.67 即使使用自动参数)。

在标准 C++ 中重写函数的常规方法是应用模板:

template<typename T, typename U>
auto multiplication(T a, U b)
{
    return a * b;
}

并让编译器推断返回类型。

【讨论】:

  • 我不确定这是正确的解释。使用__PRETTY_FUNCTION__ ,输出为auto multiplicatio(auto:1, auto:2) [with auto:1 = int; auto:2 = double]T不能同时推导出intdouble
  • @DavideSpataro 你用的是什么版本的GCC
  • 不是最新的,但应该足够新:g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
  • @DavideSpataro 我在 wandbox 上尝试了 gcc 5.3gcc 5.4 并且都给出了相同的结果:0 0.67。另一方面,gcc 7.1 给出0.67 0.67。这就是为什么我认为扩展无法正常工作并生成类似于答案中提到的模板并带有某种类型的参数转换的原因。
  • @DavideSpataro 是的,但是 lambdas 是做这些事情的标准方法,而自动参数不是:) 所以扩展似乎不能在旧的 gcc 版本上正常工作。
【解决方案2】:

首先,Bjarne Stroustrup 在他的开创性著作第 4 版中提到 "The C++ Programming Language" 并没有提到代码示例中呈现的 auto 的使用。而是以auto specifier 的标准用法为:

  • 变量的说明符,其类型将由其初始化程序推断(例如,auto i = 0;)。
  • 函数返回类型的说明符,它将由其尾随返回类型或其返回语句推导出来。

    auto foo(int a, int b) {return a + b; }

在您的示例中,您指的是使用auto 作为C++ extensions for Concepts (N4674) 提案所建议的占位符。不幸的是,这还不是标准的 C++。它本应在 C++17 中被接受,但没有成功。现在对 C++20 寄予厚望。然而,像 auto 这样的使用由 GCC 提供为 extension。 GCC 的 C++ 概念工作很早就开始了,甚至早于 C++11 的出现。在某些时候,概念工作被放弃,然后以另一个名称重新启动,即 Concepts Lite。当时的支持非常不稳定(例如,GCC 5.4 版)。因此,您遇到的是 GCC 错误。在最新版本的 GCC 中,此错误已得到纠正。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    相关资源
    最近更新 更多