Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

initialisation et double déclaration de données static d'un objet non instancié

119 réponses
Avatar
heinquoi
Bjr,
j'ai un pb de compréhension sur ce code:

class Main
{
public:
static HINSTANCE hInstance;
static HINSTANCE hPrevInstance;
static int nCmdShow;
static int MessageLoop( void );
};

HINSTANCE Main::hInstance = 0; // ici, je devrais avoir une
erreur
HINSTANCE Main::hPrevInstance = 0; // ici, aussi

il y a une double déclaration non ?
Si quelqu'un peut m'éclairer ? Et l'objet n'est meme pas initialisé.
Cordialement
Heinquoi

9 réponses

8 9 10 11 12
Avatar
Gabriel Dos Reis
writes:


[...]

| > A mon avis, on trouve l'operator<< (qui a un linkage externe) par le
| > recherche utilisant les namespace associes dans le contexte de
| > l'instanciation (le dump dans main). Comme il n'y a qu'une unite de
| > traduction et que le contexte d'instanciation comporte toutes les
| > declarations de linkage externe de celle-ci, le dernier paragraphe
| > n'est pas a considerer.
|
| C'est ce que je commence à croire moi-même.

Quelqu'un peut m'expliquer pourquoi ?


| C'est que selon ma premier
| analyse, C ne se trouvait pas dans un namespace ; c'est donc que la

3.3.5/3 dit qu'il se trouve dans un namespace. Quel passage de la
norme dit le contraire ?

| recherche dépendante aux paramètres ne pourrait pas le retrouver. Mais
| tout compte fait, je crois que la norme considère le namespace global
| comme n'importe quel autre namespace

La norme dit explicitement que la portée globale est un namespace.

| -- l'absense d'un namespace, c'est un namespace.

Hein ?

| C'est raisonable, mais dans ce cas-là, pourquoi ne pas y mettre les
| types de base aussi ?

Ils n'y sont pas déclarés.

| Mais je deviens de plus en plus confus. Ce qui m'a mis la puce à
| l'oreille, c'est que je me suis rappelé d'un cas où on avait surchargé
| l'opérateur << pour un std::vector< double >, et que le compilateur n'a
| pas trouver ce surcharge quand on utiliser un std::ostream_iterator. (Je
| crois que c'était le cas. Je n'ai plus le code exact sous la main.) OK,
| je comprends. Le problème, c'est que double, c'est un type de base, qui
| n'est dans aucun namespace, même pas le namespace global. Sauf que je
| viens d'essayer avec mon exemple ci-dessus, en remplaçant C par
| std::vector<double>, et ça compile aussi. Alors, pourquoi ça compile
| avec mon template dump, et non avec ostream_iterator ?

Quel compilateur utilises-tu ?

(J'ai différentes explications pour différents compilateurs, si si :-)).

| Une question subsidiaire serait : est-ce que le tout n'est pas un peu
| trop compliqué ?

Bah, je sais pas. Dns le cas particulier que tu donnes, non.

| Au point, même, que si on se sert des templates, on ne
| peut plus savoir si son code est correct ou non.

Meuh si, dans la plupart des cas.

-- Gaby
Avatar
Gabriel Dos Reis
Jean-Marc Bourguet writes:

[...]

| > > A mon avis, on trouve l'operator<< (qui a un linkage externe) par le
| > > recherche utilisant les namespace associes dans le contexte de
| > > l'instanciation (le dump dans main). Comme il n'y a qu'une unite de
| > > traduction et que le contexte d'instanciation comporte toutes les
| > > declarations de linkage externe de celle-ci, le dernier paragraphe
| > > n'est pas a considerer.
| >
| > C'est ce que je commence à croire moi-même. C'est que selon ma premier
| > analyse, C ne se trouvait pas dans un namespace ; c'est donc que la
| > recherche dépendante aux paramètres ne pourrait pas le retrouver. Mais
| > tout compte fait, je crois que la norme considère le namespace global
| > comme n'importe quel autre namespace -- l'absense d'un namespace, c'est
| > un namespace.
|
| C'est ce que je comprends.

Mais la portée globale est une portée de namespace. Pour quelles
raisons penses-tu que Koenig lookup ne devrait pas s'appliquer ?

| > C'est raisonable, mais dans ce cas-là, pourquoi ne pas y mettre les
| > types de base aussi ?
|
| J'ai ete surpris de l'apprendre quand j'essayais de faire une
| proposition pour un "typedef" introduisant des nouveaux types plutot
| que des synonymes. J'ai donc pas de bonne reponse.
|
| > Mais je deviens de plus en plus confus. Ce qui m'a mis la puce à
| > l'oreille, c'est que je me suis rappelé d'un cas où on avait surchargé
| > l'opérateur << pour un std::vector< double >, et que le compilateur n'a
| > pas trouver ce surcharge quand on utiliser un std::ostream_iterator. (Je
| > crois que c'était le cas. Je n'ai plus le code exact sous la main.) OK,
| > je comprends. Le problème, c'est que double, c'est un type de base, qui
| > n'est dans aucun namespace, même pas le namespace global. Sauf que je
| > viens d'essayer avec mon exemple ci-dessus, en remplaçant C par
| > std::vector<double>, et ça compile aussi. Alors, pourquoi ça compile
| > avec mon template dump, et non avec ostream_iterator ?
|
| como refuse

[...]

Comme il se doit.

-- Gaby
Avatar
kanze
Jean-Marc Bourguet wrote in message
news:...
writes:

Une question subsidiaire serait : est-ce que le tout n'est pas un
peu trop compliqué ? Au point, même, que si on se sert des
templates, on ne peut plus savoir si son code est correct ou non.


Qu'est est l'antecedant de "tout"?


Tout:-). Disons la récherche des noms dans un template.

Quelles sont les alternatives?


Ce que la plupart des compilateurs implémentent déjà ? Je ne sais pas.
D'abord, il faudrait définir le problème qu'on essaie à résoudre. Puis,
il faut comparer le coût de la solution proposée avec le coût de vivre
avec le problème.

Quel est la situation minimale acceptable?


Quelque chose qu'un programmeur moyen est capable à comprendre et à
assimuler.

La recherche des noms et les templates ont des interactions complexes,
mais je crains que pour trouver des alternatives significativement
plus simples, il faille perdre en fonctionnalite/facilite
d'utilisation.


Par exemple ?

Côté simplicité et facilité d'utilisation, il n'y a rien à dire contre
faire toute la récherche lors de l'instantiation, dans le contexte
d'instantiation, comme si c'était une fonction quelconque écrite dans ce
contexte. C'est une solution qui comporte un certain nombre de risques,
je l'avoue.

Le problème que je vois actuellement c'est simple. Je régarde les gens
avec qui je travaille. Il n'y en a pas un qui sache comment marche la
récherche des noms dans les templates. Moi-même non plus, je ne le
connais pas complètement. Et j'essaie. J'ai du mal, et je crois que si
j'ai du mal, ça ne va pas être facile pour les gens avec qui je
travaille non plus.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Jean-Marc Bourguet
Gabriel Dos Reis writes:

Jean-Marc Bourguet writes:

[...]

| > > A mon avis, on trouve l'operator<< (qui a un linkage externe)
| > > par le recherche utilisant les namespace associes dans le
| > > contexte de l'instanciation (le dump dans main). Comme il n'y
| > > a qu'une unite de traduction et que le contexte
| > > d'instanciation comporte toutes les declarations de linkage
| > > externe de celle-ci, le dernier paragraphe n'est pas a
| > > considerer.
| >
| > C'est ce que je commence à croire moi-même. C'est que selon ma
| > premier analyse, C ne se trouvait pas dans un namespace ; c'est
| > donc que la recherche dépendante aux paramètres ne pourrait pas
| > le retrouver. Mais tout compte fait, je crois que la norme
| > considère le namespace global comme n'importe quel autre
| > namespace -- l'absense d'un namespace, c'est un namespace.
|
| C'est ce que je comprends.

Mais la portée globale est une portée de namespace. Pour quelles
raisons penses-tu que Koenig lookup ne devrait pas s'appliquer ?


Je ne l'ai jamais pense.

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
Loïc Joly
Gabriel Dos Reis wrote:
writes:

| Je me rappelle des histoires, mais l'objet dans
| le namespace global était toujours un type de base, comme double.

Ces histoires sont un peu différentes : la raison est que l'ensemble
des namespaces associés à un type fondamental ou composite de types
fondamentaux est vide -- donc Koenig lookup s'applique mais ne trouve
rien.


Quel est l'interêt à ne pas avoir postulé << l'ensemble des namespace
associés à un type fondamental ou composite de types fondamentaux est
{::} >> ?

Voire même leur associer {::, std::}.

N'aurait-ce pas été plus homogène ? Intuitivement[1], j'aimerai bien que
double ait le même comportement, par exemple, que std::complex<double>.


[1] Je sais qu'il est classique de devoir laisser son intuition au
vestiaire en C++, mais j'aimerai bien que la liste de ces situations
soit la plus faible possible.

--
Loïc

Avatar
Gabriel Dos Reis
Loïc Joly writes:

| Gabriel Dos Reis wrote:
| > writes:
| > | Je me rappelle des histoires, mais l'objet dans
| > | le namespace global était toujours un type de base, comme double.
| > Ces histoires sont un peu différentes : la raison est que l'ensemble
| > des namespaces associés à un type fondamental ou composite de types
| > fondamentaux est vide -- donc Koenig lookup s'applique mais ne trouve
| > rien.
|
| Quel est l'interêt à ne pas avoir postulé << l'ensemble des namespace
| associés à un type fondamental ou composite de types fondamentaux est
| {::} >> ?

Je ne vois pas l'intérêt à le faire -- d'autant plus qu'il n'y a pas
de déclartion pour ces types, ni pour les fonctions correspondantes.

| Voire même leur associer {::, std::}.

Quel esy l'intérêt ?

| N'aurait-ce pas été plus homogène ?

Je ne vois pas d'homogéneité -- je vois surtout une liste de cas
spéciaux. (D'accord, il y en a déjà, mais je ne vois pas de raison
particulière d'en ajouter).


| Intuitivement[1], j'aimerai bien
| que double ait le même comportement, par exemple, que
| std::complex<double>.

Vraiment ?

-- Gaby
Avatar
drkm
Gabriel Dos Reis writes:

drkm writes:

| Gabriel Dos Reis writes:

[static fait que le template n'est pas trouvé]

| C'est donc bien le comportement prescrit par la norme ?

Oui, monsieur.

| Il faut
| l'écarter, même si elle est trouvée dans la même TU (je demande
| confirmation, car cela m'étonne) ?

Oui, monsieur.

| Peux-tu me donner une référence de verset, stp ?

Oui, monsieur.

14.6.4.2/1

[...]


Quelle est l'intention derrière tout cela ? J'aurais attendu que le
template soit trouvé, et je ne trouve pas de raison de dire le
contraire à cause du static.

--drkm

Avatar
darkman_spam
Jean-Marc Bourguet wrote in message news:...

como refuse

#include <vector>

template <typename T>
int f(T t) {
return g(t);
}

int g(double) {
return 4;
}

int g(std::vector<double>const&) {
return 5;
}

namespace ns {
class Y {
};

int g(Y) {
return 6;
}
}

int foo(double x) {
std::vector<double> v;
ns::Y y;

return f(x)
+ f(v)
+ f(y);
}

avec des erreurs pour f<double> et f<std::vector<double> > et pas pour
f<ns::Y> comme je m'y attendais (double pas de namespace associe,
std::vector a std comme namespace associe). Donc pour moi c'est
bug/not implemented yet dans le compilateur que tu as essaye


Mince alors. J'aurais dit que toutes trois auraient été trouvées.
`ns::g()' par Koenig Lookup, et les deux autres par la recherche de
noms "usuelle", puisque dans le même espace de noms que
l'instantiation. Je pensais que le Koenig Lookup ne prenait place
qu'en cas d'échec de la recherche de noms "usuelle". 3.4.1/3 semble
dire le contraire, que le Koenig Lookup remplace la recherche
"usuelle" dans le cas d'une fonction (c'est bien cela ?).

En tout cas, je me rend compte que je me suis mélangé les pinceaux
depuis fort longtemps, apparemment, sur le sujet de la recherche de
noms.

Quelqu'un pourrait-il faire ici une petite synthèse du sujet ? Avec
versets et peut-être quelques pointeurs ? Je sais, j'en demande
beaucoup :-). Mais une petite clarification ou une URL serait
vraiment la bien venue.

--drkm

Avatar
Gabriel Dos Reis
drkm writes:

[...]

| Quelle est l'intention derrière tout cela ? J'aurais attendu que le
| template soit trouvé, et je ne trouve pas de raison de dire le
| contraire à cause du static.

Si on commence à donner à static des propriétés qui ne cadrent pas
vraiment avec son propos initiale, pourquoi s'arrêter en si bon chemin ?


Une fonction nno-membre statique appartient à une unité de traduction.
Les instantiations de template, non ; elles appartiennent à des unités
d'instantiation (que la norme ne définit pas vraiment). Grosoo modo,
ces unités instantiations peuvent être la fusion de plusieurs unités de
traduction. Pour diminuer l'effet de surprise, je suppose qu'on a mis
la règle spéciale pour dire que les noms de ces fonctions ne devraient
pas faire des « voyages » trans unité de traduction.

-- Gaby
8 9 10 11 12