应该decltype(foo(1))实例化constexpr函数模板foo吗? [英] Should decltype(foo(1)) instantiate the constexpr function template foo?

查看:61
本文介绍了应该decltype(foo(1))实例化constexpr函数模板foo吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码可与gcc和MSVC一起编译,但无法使用我在clang-3.5和当前中继上测试过的clang.

The following code compiles with with gcc and MSVC, but fails using clang I tested with clang-3.5 and current trunk).

template <typename T>
constexpr auto wrong = false;

template <typename T>
constexpr auto foo(const T t) -> int
{
  static_assert(wrong<T>, "");
  return {};
}

using F = decltype(foo(1));

int main() {}

clang实例化函数主体并偶然发现 static_assert .gcc和MSVC仅查看函数声明,而忽略正文中的 static_assert .

clang instantiates the function body and stumbles over the static_assert. gcc and MSVC just look at the function declaration and ignore the static_assert in the body.

如果删除constexpr,则所有编译器都可以正常编译代码.

If you remove the constexpr, all compilers compile the code just fine.

问题:
如果声明了返回类型,是否允许decltype查看函数体?

Question:
Is decltype allowed to look into the function body if the return type is declared?

我正在寻找对标准中各个部分的引用.

I am looking for a reference to the respective section in the standard.

推荐答案

历史:如评论中所述,此问题被提出为 isocpp.org线程中,哥伦布认为该代码之所以有效,是因为模板从未在未评估的操作数之内实例化,但是在clang错误报告中 ,"rsmith"反驳说,某些 decltype 表达式确实确实需要模板实例化.

History: As noted in comments, this issue was raised as CWG issue 1581. In a isocpp.org thread, Columbo argued that the code was valid because templates are never instantiated inside unevaluated operands, however on a clang bug report, "rsmith" countered that some decltype expressions definitely did require template instantiation.

clang线程通过提出自己的(非标准)标准来临时解决此问题,以使 decltype 何时实例化 constexpr 模板.从4.0版开始,clang会成功编译代码.

The clang thread temporarily resolved the issue by coming up with their own (non-standard) criteria for when decltype would instantiate a constexpr template. Since version 4.0, clang does compile the code successfully.

WG21的理查德·史密斯(Richard Smith)于2017年11月开始使用 P0859 解决此问题.这会将新文本添加到[expr.const]中,该文本实现了如上所述的clang行为:

Richard Smith of WG21 has started to address the issue as of November 2017, with P0859. This adds new text to [expr.const] which implement the behaviour of clang as discussed above:

如果表达式是可能是常量常量 :

  • 可能评估的表达式([basic.def.odr])
  • 一个约束表达式,包括一个由需求子句逻辑约束或表达式形成的,
  • 括号初始列表 [脚注:的立即子表达式:可能需要进行常量评估以确定是否执行了变窄转换([dcl.init.list]).],
  • 以模板实体形式出现的& cast-expression 形式的表达式[<脚注:这样的表达式是否取决于值([temp.dep.constexpr]).]或
  • 上述之一的子表达式,不是嵌套的未评估操作数的子表达式.
  • a potentially-evaluated expression ([basic.def.odr]),
  • a constraint-expression, including one formed from the constraint-logical-or-expression of a requires-clause,
  • an immediate subexpression of a braced-init-list[ Footnote: Constant evaluation may be necessary to determine whether a narrowing conversion is performed ([dcl.init.list]). ],
  • an expression of the form & cast-expression that occurs within a templated entity[ Footnote: Constant evaluation may be necessary to determine whether such an expression is value-dependent ([temp.dep.constexpr]). ], or
  • a subexpression of one of the above that is not a subexpression of a nested unevaluated operand.

需要常量或常量的函数 :

  • 由表达式([basic.def.odr])命名的constexpr函数,该表达式的值可能是常量,或者
  • 其名称显示为可能为常量的表达式的变量,该表达式可以是constexpr变量,也可以是非易失性const限定的整数类型或引用类型.

[temp.inst]被修改为,如果模板专用化的定义会影响程序的语义,则实例化模板专用化 ,这意味着它需要进行持续评估 >如上所述,即使实际上并不需要,也可以.

And [temp.inst] is modified to say that a template specialization is instantiated if its definition affects the semantics of the program, which means that it's needed for constant evaluation as defined above, even if it isn't actually needed, so to speak.

修改了ODR以避免Columbo的反对.

The ODR is modified to avoid Columbo's objection.

有关该建议的建议更改的确出现在N4727中,这是C ++ 17之后的草案.因此,即使P0859链接和CWG缺陷列表尚未声明,我都认为它们已被接受.

The recommended changes on that proposal do appear in N4727, which is a post-C++17 draft. So I assume they have been accepted even though the P0859 link and the CWG defect list don't say so yet.

在这些更改下,您的代码 decltype(foo(1)),表达式 foo(1)不是可能常量求值的((因为它与上面的任何要点都不匹配),因此不得实例化该模板,并且对代码进行修改以避免[dcl.constexpr]/6,应成功编译.

Under these changes, your code decltype(foo(1)), the expression foo(1) is NOT potentially constant evaluated (because it does not match any of the bullet points above), so the template must not be instantiated, and the code, with a modification to avoid [dcl.constexpr]/6, should compile successfully.

(C ++ 17 dcl.constexpr/6表示如果没有有效的专业化,则模板是格式错误的NDR;这对于 foo 是正确的,但是可以通过添加<代码>模板<> constexpr自动错误< float> = true; ).

(C++17 dcl.constexpr/6 says that a template is ill-formed NDR if there are no valid specializations; which is true for foo, however this can be fixed by adding template <> constexpr auto wrong<float> = true; for example).

这篇关于应该decltype(foo(1))实例化constexpr函数模板foo吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆