J'ai compilé et exécuté le programme suivant dans un compilateur C++ 17 (Coliru). Dans le programme, j'ai déclaré une variable extern
, mais ne l'a pas définie. Cependant, le compilateur ne donne pas erreur de l'éditeur de liens.
#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;
}
Pourquoi le compilateur ne donne-t-il pas d'erreur de l'éditeur de liens?
Parce que la variable n'est pas utilisée par odr. Tu as un constexpr if
là qui rejette toujours la branche qui pourrait l'utiliser.
L'un des points de constexpr if
est que la branche rejetée n'a même pas besoin d'être compilée, elle doit seulement être bien formée. C'est ainsi que nous pouvons placer des appels à des fonctions membres non existantes dans une branche supprimée.
Dans votre cas, la variable est utilisée uniquement dans les instructions ignorées. Cependant, même si nous ignorons ce fait, la spécification du langage C++ indique toujours explicitement que aucun diagnostic n'est requis pour les définitions manquantes
.2 Règle à une définition
4 Chaque programme doit contenir exactement une définition de chaque fonction ou variable non en ligne qui est utilisée par odr dans ce programme en dehors d'une instruction rejetée (6.4.1); aucun diagnostic requis.
La spécification du langage comprend qu'un compilateur d'optimisation peut être suffisamment intelligent pour éliminer toutes les utilisations odr d'une variable. Dans ce cas, il serait excessif et inutile d'exiger la mise en œuvre pour détecter et signaler les violations potentielles du RLL.
Parce que le compilateur produit des erreurs de compilation, le linker produirait des erreurs de l'éditeur de liens ...
Non sérieusement:
if constexpr (true)
est toujours vrai, donc le compilateur ignore le reste de la clause if car elle n'est jamais atteinte. Donc i
n'est jamais utilisé en fait.
Cela a déjà été répondu, mais si vous êtes intéressé, cppreference.com a exactement cet exemple pour constexpr if :
Constexpr If
L'instruction qui commence par
if constexpr
est connu sous le nom de constexpr if .Dans une instruction if constexpr, la valeur de la condition doit être une conversion contextuelle expression constante de type bool. Si la valeur est vraie, instruction-false est rejetée (si elle est présente), sinon, instruction-true est rejeté.
[...]
L'instruction rejetée peut odr-use une variable qui n'est pas définie:
extern int x; // no definition of x required
int f() {
if constexpr (true)
return 0;
else if (x)
return x;
else
return -x;
}