编译/非编译 丢弃模板中的 IF constexpr 子语句

compiling/non-compiling discarded if constexpr sub-statements in templates

提问人:user20575107 提问时间:6/19/2023 最后编辑:n. m. could be an AIuser20575107 更新时间:6/20/2023 访问量:45

问:

我正在阅读 If 语句的 cppreference 页面以及 C++17 标准(草案),我还发现了一个关于 stackoverflow 的(非详尽的)预先存在的问题

我的理解是,在模板中,如果 constexpr 的丢弃子语句不会被实例化,因此不会被检查(除非条件仍然依赖于值,但让我假设我们不是这种情况)。

现在,从C++17标准(第17.7节,第8条)和当前标准草案(第13.8.1节,第6节)中,我读到:

§13.8.1,第 6 条:程序格式不正确,不需要诊断,如果
§13.8.1 第 (6.1) 条:没有有效的专业化......可以为模板中的模板或 constexpr if 语句 (9.4.1) 的子语句生成,并且模板未实例化,或者
...

§13.8.1[注5:如果实例化了模板,则将根据本文档中的其他规则诊断错误。 确切地诊断出这些错误是实现质量问题。——尾注 ]

在我看来,注释似乎是添加“并且模板未实例化”只是因为在实例化的情况下,将出现标准中其他任何地方所述的编译错误。

这是否意味着可以有一个 if constexpr 的子语句,其中包含无论模板参数如何都无法编译的代码?
例如,使用:

template<typename T>
void f(){
    if constexpr(true){

    } else{
        char *p;
        float f;
        p = f;
    }
}

(1)在这种情况下,编译器应该怎么做?

(2) 有或没有实例化,行为会有所不同吗?

(3) 为什么在 godbolt 上我看到使用 clang 编译错误而不是使用 gcc ?

(4) 最后但并非最不重要的一点是,我看到 cppreference CWG2518提到一个建议,即允许在 if constexpr -> 的废弃子语句中加入 static_assert(false, ...),特别是检查“P2593R1 (static_assert(false))”的最后一部分。
阅读该提案后,对先前问题的正确答案产生了一些疑问。例如,如果 (1)/(2) 的答案是“永不错误”,那么为什么我们需要一个特定的提案来允许 static_assert(false) ?
另一方面,如果 (1)/(2) 的答案是“总是错误”,那么我很困惑为什么该提案不包含特殊规则,即使是在模板实例化的情况下,而不是仅在 (6.1) 条款中读作“并且模板未实例化”。

C++ 模板 C++17 IF-constExpr

评论

0赞 n. m. could be an AI 6/20/2023
6.1 中的子句“并且模板未实例化”对我来说没有多大意义。我认为这是一个编辑错误。
0赞 n. m. could be an AI 6/20/2023
至于编译器的不同行为,“无需诊断”就是这个意思。一个编译器选择发出诊断,尽管这不是必需的。另一个没有。两者都是对的。
0赞 user20575107 6/20/2023
对于问题(3)的“不需要诊断”,可以。关于“并且模板未实例化”,我看到它与注释“如果模板被实例化,将根据本文档中的其他规则诊断错误......”有关,因此它不应该是编辑错误。回到示例:(5) else 子语句是否被丢弃,因此没有实例化(如在模板中),因此没有检查?(6)如果真的没有检查,我们为什么要落入第(6.1)条,让叮叮当当抱怨?我有一种模棱两可的感觉。
0赞 n. m. could be an AI 6/20/2023
“如果实例化了模板,则将根据本文档中的其他规则诊断错误...”这是一个错误,因为即使模板被实例化,如果子语句不需要实例化,则 constexpr 也不一定被诊断出来。“我有一种模棱两可的感觉。”你的感觉没有错,我也不认为标准语言很清楚。
0赞 user20575107 6/20/2023
我经常有一种缺乏清晰感的感觉,但我通常会找到一种一致性。当第 6.1 条读到“没有有效的专业化......可以为模板生成“,也就是说,只有当”错误“的子语句肯定不会被丢弃时(因此在我的示例中是错误的)。另一方面,在我看来,“或模板中 constexpr if 语句的子语句”部分意味着,当没有实例化时,它是否被丢弃并不重要(注释应避免给人一种有/没有实例化的等效行为的感觉)。

答: 暂无答案