[intro.compliance.general]/2指定编译器应如何处理给定的程序。
特别是它有两点处理格式错误的程序。(2.2) 要求编译器针对违反可诊断规则的情况发出至少一个诊断。(2.3) 指出,对于违反不需要诊断的规则的程序,没有对编译器强加任何要求。
不幸的是,我认为该段落没有明确说明这两个要求之间的优先级。如果程序包含违反需要诊断的可诊断规则的情况以及违反不需要诊断的规则的情况,编译器是否需要发出诊断?
作为一个例子(被视为一个完整的单翻译单元程序):
// ill-formed, diagnostic required
int main() { using T = void&; }
// IFNDR according to [temp.res.general]/8.1 and [temp.res.general]/8.4
void f(auto) { using T = void&; }
Run Code Online (Sandbox Code Playgroud)
此外,如果 IFNDR 优先,则同样可能适用于通常被视为运行时 UB 的未定义行为,例如
// always runtime undefined behavior
int main() { return *(int*)0; }
// ill-formed, diagnostic required
using T = void&;
Run Code Online (Sandbox Code Playgroud)
那么从技术上讲也不需要诊断(被视为一个完整的单翻译单元程序)?
从实现质量的角度来看,我认为编译器在这种情况下应该尽可能发出诊断。
但我的印象是,该标准实际上并不要求这样做,这也是我之前读到/听到的。例如,[temp.res.general]/8.1中的“并且模板未实例化”的限定否则没有多大意义。然而,在其他时候,标准不使用似乎应该需要的此类反转限定,例如[dcl.constexpr]/6。
以下代码在选择 C++ 17 作为语言的 VS2019(版本 16.11.15)中编译没有错误。但它在 C++ 20 中失败,并出现错误“错误 C2027:使用未定义类型‘Anon’”
template <typename T> class a_template
{
public:
void do_something(class Anon& anon) const;
};
template <typename T> void a_template<T>::do_something(class Anon& anon) const
{
anon.do_something();
}
Run Code Online (Sandbox Code Playgroud)
该类Anon当然是未定义的,但 ::do_something 函数未使用,因此不需要实例化。这在 C++17 中没问题,但在 C++20 中显然不行。
这是语言规则的改变吗?如果是这样,是否可以在不实际定义的情况下修复它Anon?