以下代码使用gcc和MSVC编译,但使用clang失败,我使用clang-3.5和当前主干进行了测试)。
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
。
如果您删除Constexpr,所有编译器都会很好地编译代码。
问题:
如果声明了返回类型,是否允许decltype查看函数体?
我正在寻找标准中相应章节的参考。
历史:如评论意见所述,此问题作为CWG问题1581提出。在一个 isocpp.org 线程中,Columbo认为代码是有效的,因为模板从未在未计算的操作数中实例化,但是在clang错误报告中,“rsmith”反驳说,一些decltype
表达式肯定需要模板实例化。
clang线程通过为< code>decltype何时实例化< code>constexpr模板提出自己的(非标准)标准,暂时解决了这个问题。从4.0版开始,clang确实成功地编译了代码。
WG21的理查德史密斯已于2017年11月开始解决这个问题,P0859。这会向 [expr.const] 添加新文本,该文本实现了如上所述的叮当行为:
如果是以下情况,则表达式可能是常量求值:
形式的表达式
如果是,则需要一个函数或变量来进行持续评估:
由表达式([basic.def.odr])命名的constexpr函数,该表达式可能是常量求值,或者
一种变量,其名称显示为一个潜在的常量求值表达式,该表达式要么是constexpr变量,要么是非易失常量限定整型或引用型
修改后的[temp.inst]表示,如果模板专门化的定义影响程序的语义,则会对其进行实例化,这意味着需要它进行如上定义的常量求值,即使实际上并不需要它。
ODR被修改以避免哥伦布的反对。
对该提案的建议更改确实出现在N4727中,这是后C 17草案。因此,我假设它们已被接受,即使P0859链接和CWG缺陷列表尚未如此。
在这些更改下,您的代码
dectype(foo(1))
,表达式foo(1)
不是潜在的常量评估(因为它与上面的任何要点都不匹配),因此模板不得实例化,并且代码经过修改以避免[dcl.constexpr]/6,应该会成功编译。
(C 17 dcl.constexpr/6指出,如果没有有效的专门化,模板就是格式不良的NDR;这对于< code>foo
来说是正确的,但是这可以通过添加< code >模板来解决
[dcl.spec.auto]/14国[强调我的]: 显式实例化声明不会导致使用占位符类型声明的实体的实例化,但也不会阻止根据需要对该实体进行实例化以确定其类型。[示例: -结束示例] 和[temp.explicat]/11声明[强调我的]: 现在,考虑我们是否在类模板中的friend声明中定义了friend函数: 如果在同一翻译单元中实例化了的多个专门化,则将违反[basic.def.odr]/
我正在从事一个C语言的项目,当我显式实例化模板类时,很难理解模板类的哪些成员被显式实例化。我编写了以下文件,然后使用Visual C 2008 Express Edition的发布配置编译该文件,然后将其放入反汇编程序。 忽略这个文件目前并不真正需要模板,这可以很好地编译。我将exe放入反汇编程序,它告诉我该测试 这导致测试
函数模板、成员函数模板、或类模板的成员函数或静态数据成员的专门化可以在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于在翻译单元内具有实例化点的任何这样的专门化,翻译单元的末尾也被认为是实例化点。类模板的专门化在翻译单元中最多有一个实例化点。任何模板的专门化都可能在多个翻译单元中具有实例化点。如果两个不同的实例化点根据一个定义规则赋予一个模板专门化不同的含义,则程序是格式不良的,不需要诊
可变模板有很多优点,但在某些情况下,C型可变函数(使用
本文向大家介绍C++函数模板与类模板实例解析,包括了C++函数模板与类模板实例解析的使用技巧和注意事项,需要的朋友参考一下 本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解。具体内容如下: 泛型编程(Generic Programming)是一种编程范式,通过将类型参数化来实现在同一份代码上操作多种数据类型,泛型是一般化并可重复使用的意思。泛
我想确认这个代码是合法的(还是不合法的?)C++17。 如果用G++和MSVC编译,我不会得到错误(并得到正确的输出), 但Intel和clang给出了一个错误: 使用编译(对于MSVC)。 在godbolt和我的本地机器上尝试了最新的编译器。