Quelqu'un peut-il expliquer pourquoi le code suivant ne se compile pas? Au moins sur g ++ 4.2.4.
Et plus intéressant, pourquoi cela se compilera-t-il lorsque je lancerai MEMBER sur int?
#include <vector>
class Foo {
public:
static const int MEMBER = 1;
};
int main(){
vector<int> v;
v.push_back( Foo::MEMBER ); // undefined reference to `Foo::MEMBER'
v.push_back( (int) Foo::MEMBER ); // OK
return 0;
}
Réponses:
Vous devez réellement définir le membre statique quelque part (après la définition de classe). Essaye ça:
Cela devrait se débarrasser de la référence non définie.
la source
Le problème vient d'un conflit intéressant de nouvelles fonctionnalités C ++ et de ce que vous essayez de faire. Jetons d'abord un coup d'œil à la
push_back
signature:Il attend une référence à un objet de type
T
. Sous l'ancien système d'initialisation, un tel membre existe. Par exemple, le code suivant se compile très bien:C'est parce qu'il y a un objet réel quelque part qui a cette valeur stockée dedans. Si, cependant, vous passez à la nouvelle méthode de spécification des membres const stat, comme vous l'avez ci-dessus,
Foo::MEMBER
n'est plus un objet. C'est une constante, un peu semblable à:Mais sans les maux de tête d'une macro de préprocesseur (et avec la sécurité de type). Cela signifie que le vecteur, qui attend une référence, ne peut pas en obtenir une.
la source
(int)
distribution) se produit dans l'unité de traduction avec une visibilité parfaite de la constante, et leFoo::MEMBER
n'est plus utilisé . Cela contraste avec le premier appel de fonction, où une référence est transmise et évaluée ailleurs.void push_back( const T& value );
?const&
peut se lier avec rvalues.La norme C ++ nécessite une définition pour votre membre const statique si la définition est en quelque sorte nécessaire.
La définition est obligatoire, par exemple si son adresse est utilisée.
push_back
prend son paramètre par référence const, et donc strictement le compilateur a besoin de l'adresse de votre membre et vous devez le définir dans l'espace de noms.Lorsque vous transtypez explicitement la constante, vous créez un temporaire et c'est ce temporaire qui est lié à la référence (selon des règles spéciales dans la norme).
C'est un cas vraiment intéressant, et je pense en fait qu'il vaut la peine de soulever un problème afin que le std soit changé pour avoir le même comportement pour votre membre constant!
Bien que, d'une manière étrange, cela pourrait être considéré comme une utilisation légitime de l'opérateur unaire «+». Fondamentalement, le résultat de la
unary +
est une rvalue et donc les règles de liaison des rvalues aux références const s'appliquent et nous n'utilisons pas l'adresse de notre membre const statique:la source
push_back
était aconst &
. L'utilisation directe du membre a eu pour conséquence que le membre était lié à la référence, ce qui exigeait qu'il ait une adresse. Cependant, l'ajout de+
crée un temporaire avec la valeur du membre. La référence se lie alors à celle temporaire plutôt que d'exiger que le membre ait une adresse.Aaa.h
Aaa.cpp
la source
Je ne sais pas pourquoi le casting fonctionne, mais Foo :: MEMBER n'est pas alloué avant le premier chargement de Foo, et puisque vous ne le chargez jamais, il n'est jamais alloué. Si vous aviez une référence à un Foo quelque part, cela fonctionnerait probablement.
la source
Avec C ++ 11, ce qui précède serait possible pour les types de base comme
La
constexpr
partie crée une expression statique par opposition à une variable statique - et qui se comporte exactement comme une définition de méthode en ligne extrêmement simple. Cependant, l'approche s'est avérée un peu bancale avec les constexprs de chaîne C dans les classes de modèle.la source
En ce qui concerne la deuxième question: push_ref prend la référence comme paramètre, et vous ne pouvez pas avoir de référence à memeber const statique d'une classe / structure. Une fois que vous appelez static_cast, une variable temporaire est créée. Et une référence à cet objet peut être passée, tout fonctionne très bien.
Ou du moins mon collègue qui a résolu cela l'a dit.
la source