web-dev-qa-db-fra.com

Pourquoi cette "variable externe non définie" n'entraîne-t-elle pas une erreur de l'éditeur de liens en C ++ 17?

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?

38
msc

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.

58
StoryTeller

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.

41
AnT

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.

9
Rene

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;
}
1
Fabio Turati