为什么这个“未定义的外部variables”导致C ++ 17中的链接器错误?

我已经编译并在C ++ 17编译器(Coliru)中运行以下程序。 在程序中,我宣布了一个externvariables,但没有定义它。 但是,编译器不会给出链接器错误

 #include <iostream> extern int i; // Only declaration int func() { if constexpr (true) return 0; else if (i) return i; else return -1; } int main() { int ret = func(); std::cout<<"Ret : "<<ret<<std::endl; } 

为什么编译器不提供链接器错误?

因为这个variables没有被使用。 你有一个constexpr if总是丢弃可以使用它的分支。

其中constexpr if一个要点就是被丢弃的分支甚至不需要编译,只有格式良好。 这就是我们如何将调用放在不存在的成员函数放在一个废弃的分支。

在你的情况下,variables只用于放弃语句。 但是,即使我们忽略了这一事实,C ++语言规范仍然明确规定缺less定义不需要诊断

3.2一个定义的规则

(4)每个程序只能包含在该程序中被丢弃的语句(6.4.1)以外的每个非内联函数或variables的定义。 不需要诊断

语言规范理解优化编译器可能足够聪明,以消除variables的所有odr用法。 在这种情况下,要求实施检测和报告潜在的ODR违规行为将是过度的,没有必要的。

由于编译器生成编译器错误, 链接器会产生链接器错误…

不,严重:

 if constexpr (true) 

总是如此,所以编译器会忽略if子句的其余部分,因为它永远不会到达。 所以i从来没有用过。

这已经得到了回答,但是如果你有兴趣, cppreference.com正好具有这个例子, 如果

Constexpr如果

if constexpr开头的语句被称为constexpr if语句

在constexpr if语句中, condition的值必须是一个上下文转换的booltypes的常量expression式 。 如果该值为true,那么将抛弃statement-false (如果存在),否则将丢弃statement-true
[…]
丢弃的语句可以使用一个未定义的variables:

 extern int x; // no definition of x required int f() { if constexpr (true) return 0; else if (x) return x; else return -x; }