Initialisation de membre statique dans un modèle de classe

148

J'aimerais faire ceci:

template <typename T>
struct S
{
    ...
    static double something_relevant = 1.5;
};

mais je ne peux pas puisque ce something_relevantn'est pas de type intégral. Cela ne dépend pas T, mais le code existant dépend du fait qu'il soit un membre statique de S.

Puisque S est un modèle, je ne peux pas mettre la définition dans un fichier compilé. Comment résoudre ce problème?

Alexandre C.
la source
s'applique également au std::stringtype
Trevor Boyd Smith
Depuis C ++ 11, le mot clé inline a changé afin que les variables statiques puissent être initialisées au point de déclaration. Ainsi, la déclaration pour cela ressemblerait à "double statique en ligne something_relevant = 1.5;"
@ user8991265 Je crois que les variables en ligne sont disponibles depuis C ++ 17, pas C ++ 11.
zupazt3

Réponses:

196

Définissez-le simplement dans l'en-tête:

template <typename T>
struct S
{
    static double something_relevant;
};

template <typename T>
double S<T>::something_relevant = 1.5;

Puisqu'il fait partie d'un modèle, comme avec tous les modèles, le compilateur s'assurera qu'il n'est défini qu'une seule fois.

sbi
la source
4
@sbi: cela ne viole-t-il pas la règle d'une définition unique?
Alexandre C.
7
Non, pas si nous parlons de modèles. Sinon, les modèles de fonction le feraient également.
sbi
1
@sbi, @Prasoon: en fait Prasoon semble être le premier. Mais j'accepte toujours les sbi à cause du commentaire sur l'ODR (qui était ma principale préoccupation).
Alexandre C.
1
@sbi survole le texte :)
Johannes Schaub - litb
5
@Johannes: Bon sang, je suis ici depuis un an et je ne le savais pas! Que me manque-t-il d'autre? (Je me souviens encore de la honte quand j'ai découvert que les deux chiffres qui apparaissent lorsque je clique sur le nombre de votes ne sont pas un bug, mais une fonctionnalité.) <goes_playing>Wow, quand je survole votre nom, je vois votre représentant! Je ne connaissais pas celui-là non plus. @Prasoon: Non, vous avez raison, je suis arrivé itérativement là où il en est maintenant. (C'est pourquoi j'ai voté pour votre réponse, BTW.)
sbi
37

Depuis C ++ 17, vous pouvez maintenant déclarer le membre statique comme étant inline, ce qui définira la variable dans la définition de classe:

template <typename T>
struct S
{
    ...
    static inline double something_relevant = 1.5;
};

en direct: https://godbolt.org/g/bgSw1u

xaxxon
la source
1
C'est une excellente réponse. Court et précis. Voir également en.cppreference.com/w/cpp/language/static#Static_data_members pour plus d'informations.
andreee
31

Cela fonctionnera

template <typename T>
 struct S
 {

     static double something_relevant;
 };

 template<typename T>
 double S<T>::something_relevant=1.5;
Prasoon Saurav
la source
Je n'ai pas défini la variable something_relevant (j'ai supprimé l' template<typename T> double S<T>::something_relevant=1.5;)erreur de lancement du compilateur, pouvez-vous me dire quelle en est la raison?
goodman