【问题标题】:where auto keyword can't determine the type in C++其中 auto 关键字无法确定 C++ 中的类型
【发布时间】:2017-12-30 06:37:11
【问题描述】:

Auto关键字用于根据初始化推断变量的类型。但我在互联网上读到 auto 无法确定函数参数的类型。我不明白 auto 与函数参数一起使用时无法确定类型的原因。谁能告诉我为什么 auto 不能与函数参数一起使用以及任何其他不能使用 auto 关键字来确定类型的情况。

【问题讨论】:

  • int f(auto x) { auto y = x + x; return 0; } 如果你是编译器,你会在这里选择什么类型的x
  • auto 作为函数参数将与模板相同。 lambda 实际上就是这种情况。
  • @SilvioMayolo:当您在调用函数时传递参数时,为什么编译器会根据函数定义中的用法确定类型?为什么不能根据传递的参数自动判断类型?
  • @kadina,因为人们有模板。在我看来,它提供了更好的控制,而且在所有方面都更好。
  • @kadina:类型不是由使用决定的,而是由初始化决定的。 auto foo; 无效,但您之后使用 foo。

标签: c++ c++11


【解决方案1】:

“不能”是一个强词。毕竟,lambda 参数可以使用auto(在 C++14 中)。与其说是“不能”,不如说是“不能”。也许“不会”。

问题最终归结为:这实际上是做什么的?

void foo(auto x)
{
  std::cout << x << std::endl;
}

auto推导最终是基于提供一个初始化表达式,用于推导实际类型。此声明不包含初始化表达式。

C++ 是一种静态类型语言;这意味着编译器必须能够在编译时确定每个表达式和对象的类型。仅从上面,编译器就无法推断出任何东西。

那么编译器怎么知道std::cout &lt;&lt; x 是合法的C++ 语法呢?它只能判断是否存在采用std::coutxoperator&lt;&lt; 重载。如果不首先知道x 的类型,它就无法弄清楚调用了什么。它没有;对于函数的不同调用,它可能会有所不同。

但是,有一个 C++ 构造使上述内容有意义:模板。这正是在 lambda 参数中使用 auto 所做的;它隐式地将函数转换为模板函数。所以[](auto x) {return x;} 实际上变成了这样的运算符:

template<typename T>
auto operator()(T x) {return x;}

但是,这种转换并不仅仅因为将auto 作为推导语法。它必须是标准明确要求的东西。而且,除了 C++14 通用 lambda,它没有。

Concepts TS 包含此功能。然而,这只是对在函数参数列表中使用概念的能力的扩展。也就是说,他们已经有办法让函数隐式创建模板函数,所以他们只是添加了auto,本质上是“接受任何类型的概念”的一个案例。

但这在 C++20 版本的概念中被明确排除。这种排除的一般原因是,到目前为止,模板函数可以被检测到,因为它们总是必须有一些特殊的语法。即诱导物template&lt;args&gt;。在 Concepts TS 版本中,担心人们会在不知不觉中编写模板函数。

模板函数的行为与非模板函数不同。模板函数是一系列函数,因此您无法获得指向该系列本身的指针。您必须显式实例化模板才能获得指向该特定函数的指针。

【讨论】:

  • 请注意,lambdas 不存在“意外模板”风险。 lambda 是一个对象,对象不能是模板。 (它们可以包含模板,但您仍然可以拥有指向 lambda 的指针)
猜你喜欢
  • 2021-12-19
  • 1970-01-01
  • 2023-03-31
  • 2017-02-16
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-23
相关资源
最近更新 更多