10
votes

Comment résoudre une collision de nom entre un espace de noms C ++ et une fonction globale?

Si je définis un espace de noms Journal code> quelque part et rendez-le accessible dans la portée globale, cela s'affrontera avec double journal (double) code> à partir du standard CMATH en-tête. En fait, la plupart des compilateurs semblent aller avec elle - la plupart des versions de Suncc, MSVC, GCC - mais GCC 4.1.2 ne le font pas.

Malheureusement, il ne semble aucun moyen de résoudre l'ambiguïté, comme en utilisant code> Les déclarations ne sont pas légales pour les identificateurs d'espace de noms. Savez-vous de quelque manière que je puisse écrire journal :: journal code> dans l'espace de noms global même si cmath code> est inclus? P>

merci. P> EDIT STROND>: Quelqu'un voudrait-il savoir ce que la norme C ++ 03 a à dire à ce sujet? J'aurais pensé que l'opérateur de la portée suffisamment déforme l'utilisation de journal code> dans l'exemple de code ci-dessous. P>

#include <cmath>

namespace foo
{

namespace log
{

struct Log { };

} // namespace log

} // namespace foo


using namespace foo;

int main()
{
    log::Log x;

    return 0;
}

// g++ (GCC) 4.1.2 20070115 (SUSE Linux)

// log.cpp: In function `int main()':
// log.cpp:20: error: reference to `log' is ambiguous
// /usr/include/bits/mathcalls.h:110: error: candidates are: double log(double)
//     log.cpp:7: error:                 namespace foo::log { }
// log.cpp:20: error: expected `;' before `x'


8 commentaires

Pourquoi ne pas simplement l'écrire comme foo :: journal :: journal pour empêcher l'ambiguïté?


LOG n'est pas le seul membre de foo :: journal , il y en a beaucoup. Mais oui, je vais probablement finir pleinement à tous ces éléments s'il n'y a pas d'autre moyen.


@CJ: Vous voudrez peut-être consulter Cette réponse .


Ne devrait pas c identificateurs importés via les versions des en-têtes standard de C être située dans l'espace de nom std ? Est-ce un bogue de mise en œuvre V4.1 (en G ++ 4.4 ce code fonctionne bien) ou je me souviens de cette chose?


@Matteo Italia: Ces identificateurs doivent également être accessibles dans l'espace de noms global. Voir Stackoverflow. com / questions / 1524139 / ... .


@CJ: Pour autant que je sache ces citations standard, en ce qui concerne la norme, ces identificateurs doivent être mis dans l'espace de noms global que si vous incluez la C en-tête, Tout en incluant ne doit pas les mettre uniquement dans l'espace de noms std .


@Matteo: Tu as raison, j'ai mal interprété.


J'ai trouvé que ce bug sera très ennuyeux, je pourrais corriger /usr/inclufr/bits/mathcalls.h , puis le fichier attend log Par exemple, dans l'espace de noms global (voir ligne 356 dans STDLIB , il lit en utilisant :: log; . Je me demande si on peut jouer avec Toutes les macros définies afin de corriger tout ce comportement. Au fait, @Matteoitalia, je trouve cela également dans GCC 4.7, donc s'il était corrigé dans 4.4 Le bogue est revenu.


4 Réponses :


12
votes

Je suggérerais:

foo::log::Log x; // Your logging class
::log(0.0); // Log function


0 commentaires

7
votes

Bien que cela ne vous aide pas, l'erreur de GCC 4.1.2 est incorrecte. Le journal en code> dans journal :: journal code> ne peut se référer qu'au nom d'une classe ou d'espace de noms.

Si votre code doit également compiler avec GCC 4.1.2, il y a alors Deux options: p>

  1. Utilisez le nom complet FOO :: LOG :: Journal CODE> LI>
  2. Utilisez un alias d'espace de noms: LI> OL>
        namespace log1 = foo::log;
        log1::Log logger;
    


2 commentaires

+1 pour l'idée d'utiliser un alias. Êtes-vous sûr que l'erreur est incorrecte? Je suppose que vous voulez dire que l'opérateur d'étendue résout l'ambiguïté car elle ne peut pas être appliquée à un nom de la fonction? Je ne suis pas sûr de ce que la norme dit à propos de ce cas particulier. Mais en ce qui concerne les définitions d'espace de noms, voir la section 7.3.1: "L'identifiant dans une définition d'espace de nom d'origine n'aura pas été défini précédemment dans la région déclarative dans laquelle la définition de l'espace de nom d'origine apparaît."


Je suis sûr que l'erreur est incorrecte. Je devais la regarder dans la norme et, selon la grammaire, un nom de classe ou d'espace de noms peut survenir avant l'opérateur de la portée. La déclaration de votre journal n'est pas un problème, car il n'est pas défini dans la même espace de noms que la fonction journal . (Espace de noms avec l'espace de noms FOO est dans l'espace de noms global)



1
votes

CMATH utilise :: journal Pour une raison quelconque de la réception de la portée globale et ne peut pas choisir entre la fonction et votre espace de noms.

Espaces de noms Gardez le code contenait pour prévenir confusion et Pollution de signatures de fonction.

ici 'SA complète et documentée démo de approprié Espace de noms Utilisation: xxx

sortie: xxx


0 commentaires

0
votes

en C ++ 0x ou C ++ 11, les éléments suivants doivent fonctionner, compiler avec -std = c ++ 0x ou -std = C ++ 11: xxx


0 commentaires