36 votes

Ambiguïté de la liste d'initialisation des membres C ++ 11

Je suis aux prises avec ce qui semble être une ambiguïté dans c++11 symbole de résolution due à la licence GNU de la bibliothèque standard de mise en œuvre dans cet environnement:

  • Arch Linux 4.2.5-1 (x86_64)
  • g++ 5.2.0
  • clang++ 3.7.0

Exemple:

#include <iostream>
#include <string>

struct version {

  unsigned major;
  unsigned minor;
  unsigned patch;

  version(unsigned major, unsigned minor, unsigned patch) :
    major(major), minor(minor), patch(patch) { }

  friend std::ostream & operator<<(std::ostream & out, version const& v) {
    out << v.major << ".";
    out << v.minor << ".";
    out << v.patch;
    return out;
  }

};

int main(int argc, char ** argv) {
  version v(1, 1, 0);
  std::cout << v << std::endl;
  return 0;
}

Erreur de compilateur:

error: member initializer 'gnu_dev_major' does not name a non-static data
  member or base class
error: member initializer 'gnu_dev_minor' does not name a non-static data
  member or base class

Commande:

clang++ -std=c++11 -o test *.cpp

L'opérateur de résolution de portée ne semble pas être applicable dans les etats membres de l'initialisation des listes donc je ne peux pas comprendre comment résoudre l'ambiguïté. Cet exemple compile très bien sans le c++11 drapeau.

40voto

Johannes Schaub - litb Points 256113

Une autre façon consiste à utiliser des accolades:

 version(unsigned major, unsigned minor, unsigned patch) :
  major{major}, minor{minor}, patch{patch} { }
 

Ensuite, les macros n'interféreront pas car ce sont des macros similaires à des fonctions et nécessitent l'appel de parenthèses.

19voto

Myria Points 558

D'après ma propre tentative de compilation, il semblerait que glibc fasse quelque chose de stupide et #define en minuscule.

Quand j'ajoute ce qui suit après le #include s, il se compile.

 #undef major
#undef minor
 

15voto

Shafik Yaghmour Points 42198

Il ressemble major et minor sont des macros définies en sys/sysmacros.h qui est apporté par <iostream>, ce qui est problématique puisque ces noms ne sont pas réservés à la mise en œuvre. Remarque si le code est réduit et nous seul comprennent sys/sysmacros.h directement le même problème va se produire.

Quand je compile ce avec clang sur Wandbox , j'obtiens cette erreur plus informatif qui nous permet de voir où le conflit est à venir à partir de:

 usr/include/x86_64-linux-gnu/sys/sysmacros.h:67:21: note: expanded from macro 'major'
 # define major(dev) gnu_dev_major (dev)
                     ^~~~~~~~~~~~~~~~~~~

 usr/include/x86_64-linux-gnu/sys/sysmacros.h:68:21: note: expanded from macro 'minor'
 # define minor(dev) gnu_dev_minor (dev)
                     ^~~~~~~~~~~~~~~~~~~

On peut trouver ce document dans la suite de rapport de bug identifiant les principaux macro développée en gnu_dev_major:

Le problème est que g++ ajoute -D_GNU_SOURCE et majeur() est une macro dans _GNU_SOURCE (ou _BSD_SOURCE ou si aucun jeu de fonctionnalités est demandé).

Vous pouvez toujours #undef majeur après, y compris les en-têtes.

et:

makedev(), majeur() et mineures() doit être fonctions, de ne pas les macros.

Il semble qu'ils ont été introduits dans GNUC >= 2 dans sys/sysmacros.h pour la compatibilité descendante. Ce n'est pas une bonne idée.

Jongler avec des macros est dangereux car il pollue le nom d'utilisateur de l'espace.

et donc, nous pouvons voir undef macros est une autre solution, et c'est malheureusement la solution recommandée, car c'est un won't fix bug:

Il n'y aura pas de changement. Si un code n'aime pas les macros, ajouter #undefs après que le #include. Les macros sont une partie de la API et en supprimant les seules causes des problèmes.

Nous pourrions utiliser {} dans le membre intializer mais cela nécessite de modifier le type des paramètres depuis les laissant comme int serait une conversion restrictive qui n'est pas autorisé. Bien sûr, en changeant les noms est également une solution possible.

Mise à jour

J'ai déposé une glibc rapport de bug. Il y a certaines questions quant à savoir si c'est vraiment un gcc ou une glibc bug, les détails sont plutôt impliqués.

9voto

Slava Points 4119

/usr/include/sys/sysmacros.h a défini les macros suivantes:

 # define major(dev) gnu_dev_major (dev)
# define minor(dev) gnu_dev_minor (dev)
# define makedev(maj, min) gnu_dev_makedev (maj, min)
 

on dirait que vous devez les défaire ou utiliser d'autres noms

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X