【问题标题】:'auto' not allowed in function prototype with Clang使用 Clang 的函数原型中不允许使用“自动”
【发布时间】:2015-08-20 08:14:48
【问题描述】:

使用带有 std=c++1y 标志的 Clang 3.5、3.6 或 3.7,以下代码无法编译:

#include <iostream>
auto foo(auto bar) { return bar; }
int main() {
  std::cout << foo(5.0f) << std::endl;
}

给出的错误是:

错误:函数原型中不允许“自动”

我在使用 g++ 4.9 时没有错误。 产生此错误是因为 Clang 尚未实现此功能,还是因为我不允许这样做而 GCC 以某种方式允许它?

【问题讨论】:

  • 我认为你不应该这样做,因为你使用它超出了范围。
  • auto 普通(非 lambda)函数的函数参数是概念 TS 的扩展。它们不是 C++14 的一部分,而这正是 C++1y 的组成部分。
  • 顺便说一句,有一个(n 非官方的?)clang branch 支持它。可以在std-discussion mailing list 上找到一些讨论。不过,我不知道那个分支的当前状态是什么。
  • BTW C++14 已发布,因此您应该使用-std=c++14(如果您的编译器没有该开关,请升级)。下一个版本暂定名为c++1z
  • gcc 4.9.x 可能是使用概念构建的,这可能就是您看到它的原因。

标签: c++ auto c++14 clang++


【解决方案1】:

正如我们从 ISO C++ 讨论邮件中看到的:decltype(auto) parameters vs. perfect forwarding 非 lambdas 的自动参数是 concepts lite 的一部分,因此不在 C++14 中:

clang 是正确的,因为我们还没有自动参数。 Concepts lite 可能会带来这些,但 C++14 没有。

如果我们将-pedantic 标志与gcc 一起使用,我们会收到以下警告:

warning: ISO C++ forbids use of 'auto' in parameter declaration [-Wpedantic]
  auto foo(auto bar) { return bar; }
           ^

所以这看起来像是一个扩展。

正如 dyp 所指出的,polymorphic lambdas 确实进入了 C++14 并允许使用自动参数,一个来自论文的示例:

// 'Identity' is a lambda that accepts an argument of any type and
// returns the value of its parameter.
auto Identity = [](auto a) { return a; };
int three = Identity(3);
char const* hello = Identity("hello");

顺便说一句,这与您要在示例中实现的功能相同。

【讨论】:

  • @coincoin 我添加了 gcc 文档的链接,-pedantic 强制编译器针对扩展发出警告,基本上是标准不允许的任何内容。
  • @ShafikYaghmour 我认为由于函数重载问题,他们没有使其成为标准?意思是用 auto 关键字函数重载可能是模棱两可的?
  • @UnKnown 正如我所说的,它是概念精简版提案的一部分,因此将伴随这些变化。
  • 第一个链接现在坏了?
【解决方案2】:

虽然您的特定语法没有适用于 C++14,但类似的选项是:

static auto foo = [](auto bar) { return bar; };

它实现了基本相同的东西。

【讨论】:

  • MM,你能解释一下为什么static auto吗?
  • @UnKnown 这意味着名称foo 具有内部链接,即其他单位无法通过名称访问它。例如,如果另一个文件转到 int foo = 5;,这可以防止意外的未定义行为。在这里使用外部链接没有多大意义,因为您无法为 lambda 编写声明(实际定义除外),因此无论如何其他单元都无法正确使用它。
【解决方案3】:

您可以改用模板:

template<class A>
A foo(A bar) { return bar; }

仅当编译器可以从上下文中推断出类型时才允许使用自动。

【讨论】:

  • 不适用于外部“C”链接,当自动版本有时
【解决方案4】:

编译器无法从上下文推断类型。

做错了什么

template<typename Y>
Y foo(Y bar){return bar;}

你必须通过值传递bar吗?

在您的情况下,您可以使用 尾随返回类型 语法:

auto foo(auto bar) -&gt; decltype(bar)

【讨论】:

  • @Bathsheba auto 不允许在参数列表中(但在 C++14 中允许返回类型为 auto 没有 -&gt;
  • 我不明白。为什么作为函数参数传递时编译器不能推断类型?
猜你喜欢
  • 2016-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 2017-04-04
  • 2016-03-02
  • 2020-08-15
  • 2017-06-16
相关资源
最近更新 更多