【问题标题】:Shouldn't decltype Trigger Compilation of its Argument?不应该 decltype 触发其参数的编译吗?
【发布时间】:2016-07-14 12:05:49
【问题描述】:

所以我对它的工作原理感到困惑。给定:

template <typename T>
int foo(T t) { t.foo(); }

看来这个调用应该失败:

decltype(foo(int{ 13 })) fail = 42;

cout << fail << endl;

改为it just prints:

42

它在我可以访问的所有编译器上都以这种方式工作。这是正确的行为吗?我请求 C++ 标准的报价。

【问题讨论】:

  • std::type_info::name() 不能保证提供任何可靠的信息。在其他情况下它会提供其他任何东西吗?
  • @StoryTeller 我已经从问题中删除了type_info。希望这有助于澄清问题。这是一个关于decltype 及其要求的问题,我只是想用type_info 来演示这个问题。
  • decltype 并不需要完整的函数定义来知道结果类型。 (See)。所以没有理由编译原型以外的任何东西。但我没有标准报价。
  • @StoryTeller 哇,这是一个很好的例子。这个概念让我大吃一惊。
  • @StoryTeller sizeof(decltype(expression)) 似乎有点多余。

标签: c++ templates compilation language-lawyer decltype


【解决方案1】:

[dcl.spec]

对于表达式 e,由 decltype(e) 表示的类型定义为 如下:

如果 e 是一个不带括号的 id 表达式,命名从分解的标识符列表中引入的左值或引用 声明,decltype(e) 是引用的类型,如 分解声明的规范([dcl.decomp]);

否则,如果 e 是无括号的 id 表达式或无括号的类成员访问 ([expr.ref]),则 decltype(e) 是 由 e 命名的实体的类型。如果没有这样的实体,或者如果 e 命名一组重载函数,程序格式错误;

否则,如果e是一个xvalue,则decltype(e)是T&&,其中T是e的类型;

否则,如果e是左值,decltype(e)就是T&,其中T是e的类型;

否则,decltype(e) 就是 e 的类型。

decltype 说明符的操作数是未计算的操作数 (子句 [expr])。

(强调我的)

所以你的foo(int{ 13 }) 永远不会被评估。

【讨论】:

  • 完美答案,谢谢。我害怕我会接受Jesper Juhl's "because I said so" answer
  • 我想知道这是否真的意味着编译必须成功。例如。在1 ? 0 : foo(int{13}) 中,该调用从未被评估过,但我不希望它能够编译。 (在类型检查未计算的操作数中究竟做了什么,可能有一些特定的规则......?)
  • 如果将上述函数模板的定义更改为template &lt;typename T&gt; auto foo(T t) { t.foo (); },模板的实例化似乎发生了——这对我来说很有意义,因为没有返回类型推导,@ 就没有办法987654326@ 产生任何东西。当然,这以编译时错误结束。在上述条款中,这种行为体现在哪里?我错过了什么吗?
  • @chi 术语 未计算的操作数 是由标准条款 [expr] 定义的艺术术语,它不仅仅意味着“未计算的操作数” .根据 [basic.def.odr],?: 运算符的第 2/3 个操作数是可能评估的操作数。 [expr] 中有一个非规范性注释:“在未计算的操作数中......对象或函数的命名本身并不要求提供定义。”
  • @thokra [decl.spec.auto]: "当定义被实例化时,即使函数体包含返回值,在其声明类型中具有占位符的函数模板的返回类型推导也会发生具有非类型相关操作数的语句。[注意:因此,任何使用函数模板的特化都会导致隐式实例化。]"
【解决方案2】:

decltype 中的表达式被标准定义为不被计算,它们仅被解析以获得表达式的类型。

【讨论】:

  • 参考宇宙主文档的强制性问题。
  • 这是一个简短的答案。我将对它发表比答案本身更长的评论:我已经确定我可以访问的编译器支持您的陈述。所以问题是:“这是正确的行为吗?”要确定您需要参考的东西比您所学的知识要多。
  • @JohannesSchaub-litb 我假设你在问:“官方来源有什么用?”我对这个问题的回答是:如果我尝试过的所有编译器碰巧实现了非标准行为,我不想编写依赖于此的代码......并且可能会纠正下一代。如果它是标准行为,那么我希望我可以依赖它,我会在代码中利用它。
  • eel.is/c++draft/dcl.type.simple#4 decltype 说明符的操作数是未计算的操作数(子句 [expr])。
  • @GillBates 你完美地总结了这个网站
猜你喜欢
  • 1970-01-01
  • 2016-04-14
  • 2016-11-19
  • 2018-08-20
  • 2019-02-06
  • 1970-01-01
  • 2020-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多