Lorsque j'essaie de compiler cela,
template <class T> T min(T const a, T const b){ return a < b ? a : b; }
3 Réponses :
Cette question est posée assez souvent. Je crois que c'est un bug de collage. A code> est désactivé comme une expression constante trop tôt et le compilateur ne génère pas de définition de celui-ci. Strike> (voir correction dans les commentaires)
std :: min Code> prend ses arguments par const Référence, une définition doit donc exister. P>
#include <iostream>
struct K{
constexpr static int a() { return 5; }
};
int main(){
K k;
std::cout << std::min(k.a(), 7);
}
IIRC aussi le niveau d'optimisation pourrait affecter cela.
@juzzlin Il ne lie pas sur Apple Clang sans optimisation. Le compilateur n'empêche pas de déterminer l'utilisation des ODR d'une option correctement.
@RICHARD HODGES OK, je me souviens juste que j'ai rencontré Ceci avec GCC sur Ubuntu et cela fonctionnait sans optimisations, mais j'ai échoué avec -O3 ou quelque chose comme ça: p
Non, ce n'est pas un bug (je pensais que c'était aussi ...). Mais une initialisation intégrale de consons statique n'est toujours pas une définition selon la norme: 9.4.2 Membres de données statiques [Class.Static.Data] §3 Si un élément de données statique de const non volatil est de type intégré ou d'énumération, son Déclaration dans la définition de la classe peut spécifier une initialisation de la corse ou égale dans laquelle chaque clause d'initialisation qui est une affectation experte est une expression constante ... Le membre doit toujours être défini dans une portée d'espace de noms s'il est odrique Utilisé b> (3.2) ... et la définition de la portée de l'espace de noms ne doit pas contenir d'initialisateur. i>
@Sergeballesta correction faite à la poste en réponse. Merci.
Cependant, dans le Si un objet est ODR-utilisé em>, il doit y avoir exactement une définition de celui-ci; sans diagnostic requis pour violer cette règle. Donc le premier cas peut être accepté ou non; et le deuxième cas doit être accepté. P>
Dans votre propre version de Vous pouvez lire l'ensemble complet des règles sur ODR-Use em> dans la section [basic.def.odr] d'un brouillon standard C ++. p> std :: min code> accepte des arguments par référence. Lier une référence à un objet signifie que l'objet est ODR-utilisé em> (il existe un échantillon de code dans [basic.def.odr] / 2 à peu près identique à votre échantillon). p>
(int) k.a code> cas,
k.a code> n'est pas odr-utilisé em>;; Parce qu'il effectue une conversion de lvalue à rvalue qui donne une expression constante. (Il y a quelques autres conditions ici aussi, mais votre code est correct). p>
min code>, il prend des arguments par valeur, ce qui est similaire à celui de
(int) ka code> - la seule action prise sur
ka Code> Il y a une conversion de rvalue pour initialiser le paramètre de votre
min code>. p>
une ligne const int k :: a; code> est ce qui manque
@ SP2Danny pas nécessairement; par exemple. Le deuxième échantillon est correct sans cette ligne
BTW, 9.4.2 Membres de données statiques [Class.Static.Data] §3 est spécifiquement explicite pour ce cas d'utilisation si un élément de données statique de const non volatil est de type intégré ou d'énumération, sa déclaration dans la définition de la classe peut Spécifiez une initialisation de la corset ou égale dans laquelle chaque clause d'initialisateur qui est une affection qui est une expression constante est une expression constante ... L'élément doit toujours être défini dans une portée d'espace de noms si elle est ODR-utilisée B> ( 3.2) Dans le programme et la définition de portée de l'espace de noms ne contiennent pas d'initialisateur. I>
Vous avez déclaré une variable statique (A) dans votre structure, mais vous ne l'avez pas définie.
struct K { const static int a; // declaration }; const int K::a = 5; // definition int main() { std::cout << std::min(K::a, 7); }
Cela ne fonctionnerait pas pour la même raison que la tentative de OP ne fonctionnerait pas.
Vous avez raison. J'utilisais g ++ -std = C ++ 11 -O2 -Wall et cela a fonctionné. Supprimer -O2 Le faire ne le faire pas. Je vais éditer la réponse.
Pourquoi GCC et CLang sont-ils marqués? Vous ne devriez utiliser qu'un seul compilateur qui, par l'apparence, est collée
ideone.com/ypq6w fonctionne pour moi
Essayez de changer votre
min code> pour prendre les paramètres par référence.
Vos exemples doivent avoir
#include code> pour
std :: min code>
Puisque C ++ 11 Une autre solution de contournement consiste à utiliser la liste de la liste de min:
std :: min ({k.a, 7}) code>. Je pense que ce n'est pas une utilisation ODR car les répertoriennes initialisées copient de la valeur. Depuis C ++ 14, le formulaire de liste donne même un
consexpr code>.
Voir aussi la réponse à Stackoverflow.com/Questtions/9928373/...