Curieux conflit entre espaces de nom

7 réponses
Avatar
Fautvoir
J'ai un problème de conflit d'espace de nommage qui me semble à moi,
assez mystérieux.

Après avoir décidé de migrer une application de gtkmm 1.2 avec plein
d'API "deprecated" vers le
toolkit gtmm 2.4, je me trouve confronté à deux problèmes que je ne
comprends pas.

Le premier, dans un fichier .hh de définition de classe :


#include <gtkmm.h>

#include <map>

class A
{
...
map <truc, machin > carte; // ne compile plus, declaration de
// map implicite interdite
};

Pour que ça compile, je remplace map par std::map. Je n'ai pas vu de
d'objet map dans les includes de gtkmm
Ca compilait avec l'ancienne version des gtkmm.

Ca, à la rigueur, il vaut mieux expliciter l'espace de nom dans les
fichiers de définition de classe. Mais je
m'attendais à un conflit d'espace de nom plutôt qu'à une erreur de
déclaration implicite.

Qu'en pensez-vous ?

Deuxième problème :

Les fichiers includes de gtkmm déclarent un objet nommé Glib::Interface.
Il n'y a aucune déclaration "using namspace XXX" dans les includes de
gtkmm (fort heureusement ! ).

J'ai aussi défini une class Interface a portée globale (en dehors de
tout espace de nom) et j'ai un fichier de définition de la classe B comme ça

#include <gtkmm.h>

class Interface;
class C;

class B : public Gtk::Window
{
Interface * interface;
C* cc;
....
};

Un autre fichier de définition de la classe C sans utilisation des
classes de gtkmm

class Interface;

class C
{

Interface * fonction();
....
};

Dans le constructuer de B

#include "C.hh"

B::B(C* ccc) :
cc(ccc)
{
interface = cc->fonction(); Ne compile plus : conversion de
Interface vers Glib::Interface interdite.
...
}

Je n'ai jamais demandé l'usage de l'espace Glib nulle part. La
définition de la classe C a défini le retour
de la fonction dans l'espace global, alors que la définition de la
classe A a définit la variable "interface"
dans l'espace de nom "Glib".

Comment cela peut-il se faire ?
N'y a t-il pas quelque chose de tellement gros que je ne le vois pas ?

7 réponses

Avatar
Jean-Marc Bourguet
Fautvoir writes:

Pour que ça compile, je remplace map par std::map. Je n'ai pas vu de
d'objet map dans les includes de gtkmm
Ca compilait avec l'ancienne version des gtkmm.



Elles pourraient avoir eu un using namespace std; dans un entête.

Ca, à la rigueur, il vaut mieux expliciter l'espace de nom dans les
fichiers de définition de classe. Mais je
m'attendais à un conflit d'espace de nom plutôt qu'à une erreur de
déclaration implicite.



Tu peux donner le message exact?

B::B(C* ccc) :
cc(ccc)
{
interface = cc->fonction(); Ne compile plus : conversion de Interface
vers Glib::Interface interdite.
...
}

Je n'ai jamais demandé l'usage de l'espace Glib nulle part. La définition
de la classe C a défini le retour
de la fonction dans l'espace global, alors que la définition de la classe A
a définit la variable "interface"
dans l'espace de nom "Glib".
Comment cela peut-il se faire ?



Un typedef de Interface ou un using namespace Glib dans la classe
Gtk::Window.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Fabien LE LEZ
On Sat, 08 Aug 2009 16:07:54 +0200, Fautvoir :

class A
{
...
map <truc, machin > carte; // ne compile plus, declaration de
// map implicite interdite
};

Pour que ça compile, je remplace map par std::map.



Je ne comprends pas bien pourquoi ça aurait dû fonctionner.

(Ou alors, tu as mis un "using namespace std" dans un .h. Mais là,
c'est vraiment chercher les emmerdes.)

class B : public Gtk::Window
{
Interface * interface;



Est-ce qu'il y a un type "Interface" dans "Gtk::Window" ?

Je sens bien un truc du style :

namespace Gtk
{
class Window
{
public:
typedef Glib::Interface Interface;
};
}
Avatar
Fautvoir
Fabien LE LEZ a écrit :
On Sat, 08 Aug 2009 16:07:54 +0200, Fautvoir :

class A
{
...
map <truc, machin > carte; // ne compile plus, declaration de
// map implicite interdite
};

Pour que ça compile, je remplace map par std::map.



Je ne comprends pas bien pourquoi ça aurait dû fonctionner.

(Ou alors, tu as mis un "using namespace std" dans un .h. Mais là,
c'est vraiment chercher les emmerdes.)




Oui, je les ai cherchés (les emmerdes et les using namespace std). Il en
subsistait quelques uns dans les .hh ...

class B : public Gtk::Window
{
Interface * interface;



Est-ce qu'il y a un type "Interface" dans "Gtk::Window" ?



Non. mais gtkmm appelle glibmm qui défini un objet de type Glib::Interface

Je sens bien un truc du style :

namespace Gtk
{
class Window
{
public:
typedef Glib::Interface Interface;
};
}




J'ai trouvé dans les .h de la glib des trucs comme cela



glibmm/private/interface_p.h: typedef Interface CppObjectType;
glibmm/private/interface_p.h: typedef GTypeInterface BaseClassType;
glibmm/interface.h: typedef Interface CppObjectType;
glibmm/interface.h: typedef Interface_Class CppClassType;
glibmm/interface.h: typedef GTypeInterface BaseClassType;

Pas de typedef XXXX Interface;

Mais dans le cas que tu donnes, le nom entier de variable ne serait-il
pas "Gtk::Window::Interface" donc sans ambiguïté avec Interface de
l'espace global ?
Avatar
Fautvoir
Jean-Marc Bourguet a écrit :
Fautvoir writes:

Pour que ça compile, je remplace map par std::map. Je n'ai pas vu de
d'objet map dans les includes de gtkmm
Ca compilait avec l'ancienne version des gtkmm.



Elles pourraient avoir eu un using namespace std; dans un entête.

Ca, à la rigueur, il vaut mieux expliciter l'espace de nom dans les
fichiers de définition de classe. Mais je
m'attendais à un conflit d'espace de nom plutôt qu'à une erreur de
déclaration implicite.



Tu peux donner le message exact?




Le voici

CMakeFiles/gestionnaire.dir/Gestion/IHM/Fenetre_principale.o
/home/thierry/Circuit/Gestion/IHM/Fenetre_principale.cc: In constructor
'Fenetre_principale::Fenetre_principale(Services*)':
/home/thierry/Circuit/Gestion/IHM/Fenetre_principale.cc:37: error:
cannot convert 'Interface*' to 'Glib::Interface*' in assignment


B::B(C* ccc) :
cc(ccc)
{
interface = cc->fonction(); Ne compile plus : conversion de Interface
vers Glib::Interface interdite.
...
}

Je n'ai jamais demandé l'usage de l'espace Glib nulle part. La définition
de la classe C a défini le retour
de la fonction dans l'espace global, alors que la définition de la classe A
a définit la variable "interface"
dans l'espace de nom "Glib".
Comment cela peut-il se faire ?



Un typedef de Interface ou un using namespace Glib dans la classe
Gtk::Window.



Pas de "using namespace XXX" dans les includes de gtkmm. Heureusement !

Merci
Avatar
Fabien LE LEZ
On Sat, 08 Aug 2009 17:30:39 +0200, Fautvoir
:

Mais dans le cas que tu donnes, le nom entier de variable ne serait-il
pas "Gtk::Window::Interface" donc sans ambiguïté avec Interface de
l'espace global ?



Ben non : vu que B dérive de Gtk::Window, tout type membre de
Gtk::Window est aussi membre de B.
Avatar
Jean-Marc Bourguet
Fautvoir writes:

Je me suis également aperçu que Gtk::Window dérive entre autres de
Glib::Interface...



Tu as ta réponse, le nom d'une classe la désigne dans la portée de la
classe.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Fautvoir
Fabien LE LEZ a écrit :
On Sat, 08 Aug 2009 17:30:39 +0200, Fautvoir
:

Mais dans le cas que tu donnes, le nom entier de variable ne serait-il
pas "Gtk::Window::Interface" donc sans ambiguïté avec Interface de
l'espace global ?



Ben non : vu que B dérive de Gtk::Window, tout type membre de
Gtk::Window est aussi membre de B.




En effet, la dérivation de la classe B de Gtk::Wndow provoque
systématiquement le choix du type Interface sur Glib::Interface

J'ai donc essayer de forcer le choix du type Interface dans l'espace
global en écrivant "::Interface" à la place de "Interface".

Le compilateur choisit alors la définition que je souhaite.

Je me suis également aperçu que Gtk::Window dérive entre autres de
Glib::Interface...