OVH Cloud OVH Cloud

fonction 'static'

31 réponses
Avatar
Michaël Delva
Bonjour à tous,

j'ai une classe avec des fonctions en 'static'

Je suis obligé d'écrire l'implémentation de ces fonctions dans le même
fichier que leur déclaration?

Merci d'avance...

10 réponses

1 2 3 4
Avatar
Gabriel Dos Reis
--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit

"Michel Michaud" writes:

| Dans news:, Jean-Marc
| > "Michel Michaud" writes:
| >
| >> Je n'ai pas le temps de vérifier ce cas dans la
| >> norme, mais à tout le moins, ceci devrait fonctionner :
| >>
| >> // A.cpp
| >> inline void A()
| >> {}
| >>
| >> // B.cpp
| >> void A();
| >>
| >> int main()
| >> {
| >> A();
| >> }
| >
| > Non. Il faut avoir une définition dans toute unité où la
| > fonction est utilisée (3.2/3).
|
| C'est ce que je comprenais aussi jusqu'à récemment. Mais j'ai
| pris une note disant que ce n'est pas le cas suite à une
| discussion vue sur un forum (je n'ai pas noté la référence
| exacte). Y aurait-il une correction à la norme (ou un DR) qui
| vient changer ce qu'on peut lire à 3.2/3 ?

--=-=- Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit


Correction sur quoi exactement ? Si une fonction est inline, elle doit
être déclarée inline dans toutes les unités de traduction, et si elle
est utilisée dans une unité de traduction, elle doit y être définie.
Et les défintions doivent s'accorder -- ODR.

--=-=- Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: 8bit


|
| (ça me ferait plaisir de me tromper, car j'ai pris la note pour
| dire que je devais corriger ce que mes livres indiquent !)
|
| --
| Michel Michaud
| http://www.gdzid.com
| FAQ de fr.comp.lang.c++ :
| http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
|

--
Gabriel Dos Reis


--=-=-=--
Avatar
Gabriel Dos Reis
"Michel Michaud" writes:

| Dans news:, Gabriel
| > "Michel Michaud" writes:
| >>> Dans la norme ok, mais dans la pratique je n'ai vu que des
| >>> compilateurs qui avaient un comportement qui faisait que
| >>> inline entrainait static, c'est à dire réduction de la portée
| >>> de la fonction.
| >>
| >> Ça fonctionne comme j'ai décrit avec VC 7.1...
| >
| > oui mais non.
| >
| >> C'est surprenant que ça ne fonctionne pas avec g++
| >
| > Parce que g++ implémente ce qu'exige la norme sur ce point.
| > C'est effectivement étrange d'implémenter ce que la norme
| > stipule, d'ailleurs je ne comprends pas pourquoi on a une norme.
|
| Je ne comprends pas pourquoi tu utilises un ton sarcastique au
| lieu de clarifier le point en litige.

Je crois que j'ai clairifié le point.

| Comme je l'ai indiqué dans
| les messages que tu as lus, j'ai l'impression qu'une discussion
| sur un forum m'a laissé une impression fausse.

Oui, mais tu ne me dis pas grand chose à part que quelqu'un aurait dit
quelque chose, mais quoi exactement ?

| En lisant tes
| trois messages, je ne suis toujours pas sûr... En particulier,
| ceci me semble contradictoire avec le reste :

Hue???

|
| MD> Une fonction inline voit sa portée limitée au fichier en
| MD> cours, donc il faut qu'elle soit définie dans le .h

Je ne comprends rien à cette phrase. Qu'est ce que inline vient faire
avec la portée ?

| MM>
| MM> Pas vraiment il me semble, en tout cas pas pour les fonctions
| MM> libres où le inline laisse le « external linkage »...
| GDR>
| GDR> Ce n'est pas ce que dit la norme.
|
| Elle ne dit pas, indirectement, que le inline ne change rien au
| linkage qui est donc externe par défaut ? Ou alors répondais-tu
| à MD, en particulier quand tu ajoutes :

Je répondais à l'affirmation que inline donne un linkage interne.

| GDR> ARM avait une règle différente (celle que tu décris), ...
|
| Le « tu » c'est MM ou MD ?
|
| Alors peux-tu confirmer avec certitude que la norme (en y
| ajoutant les points en litige notés par des DR qui pourraient
| échapper à l'attention du commun des mortels que nous sommes
| pour la plupart) indique simplement ce que je pensais il n'y
| a pas si longtemps, à savoir :
|
| - le compilateur doit voir la définition des fonctions inline
| utilisés dans chaque unité de compilation; (3.2/3)

Oui, et je l'ai explicitement dit dans l'un de mes messages.

Mais un des messages que tu as postés containait une erreur.
Si tu déclares une fonction (avec linkage externe) inline dans le
programme, alors toutes ses déclarations doivent contenir inline.

| - les fonctions inline ont quand même un linkage externe, ce
| qui assure, entre autres, qu'il n'y a qu'une seule copie des
| variables statiques qui y sont définies.

Inline n'affecte pas le linkage. Si la fonction est membre (statique
ou non), alors elle a un linkage externe et ce n'est pas inline qui va
modifier ce linkage. Si la fonction est définie à portée de namespace
et est statique (donc a un linkage interne), ce n'est pas inline qui
va changer quoi que ce soit.

| Si j'ai bon, alors c'est ce que je pensais depuis des années.
| J'en serai heureux, car je n'aurai pas à changer ce que j'ai
| écrit dans mes livres. J'aimerais juste effacer mes messages
| récents sur fclc++ :-)
|
| Il faudra bien que je trouve la discussion (j'imagine sur
| clc++m ou csc++) qui m'a fait penser qu'il y avait une
| subtilité que je ne connaissais pas. C'est intriguant, je
| n'ai certainement pas pris cette note pour rien, il fallait
| que la conclusion vienne de quelqu'un d'important...
|
| (Je suis désolé si j'ai, à mon tour, amené de la confusions sur
| ce point pourtant assez simple. Merci Gabriel d'enlever toute
| confusion dans ton prochain message !)

-- Gaby
Avatar
Michel Michaud
Dans news:, Gabriel
"Michel Michaud" writes:
Dans la norme ok, mais dans la pratique je n'ai vu que des
compilateurs qui avaient un comportement qui faisait que
inline entrainait static, c'est à dire réduction de la portée
de la fonction.


Ça fonctionne comme j'ai décrit avec VC 7.1...


oui mais non.

C'est surprenant que ça ne fonctionne pas avec g++


Parce que g++ implémente ce qu'exige la norme sur ce point.
C'est effectivement étrange d'implémenter ce que la norme
stipule, d'ailleurs je ne comprends pas pourquoi on a une norme.


Je ne comprends pas pourquoi tu utilises un ton sarcastique au
lieu de clarifier le point en litige. Comme je l'ai indiqué dans
les messages que tu as lus, j'ai l'impression qu'une discussion
sur un forum m'a laissé une impression fausse. En lisant tes
trois messages, je ne suis toujours pas sûr... En particulier,
ceci me semble contradictoire avec le reste :

MD> Une fonction inline voit sa portée limitée au fichier en
MD> cours, donc il faut qu'elle soit définie dans le .h
MM>
MM> Pas vraiment il me semble, en tout cas pas pour les fonctions
MM> libres où le inline laisse le « external linkage »...
GDR>
GDR> Ce n'est pas ce que dit la norme.

Elle ne dit pas, indirectement, que le inline ne change rien au
linkage qui est donc externe par défaut ? Ou alors répondais-tu
à MD, en particulier quand tu ajoutes :

GDR> ARM avait une règle différente (celle que tu décris), ...

Le « tu » c'est MM ou MD ?

Alors peux-tu confirmer avec certitude que la norme (en y
ajoutant les points en litige notés par des DR qui pourraient
échapper à l'attention du commun des mortels que nous sommes
pour la plupart) indique simplement ce que je pensais il n'y
a pas si longtemps, à savoir :

- le compilateur doit voir la définition des fonctions inline
utilisés dans chaque unité de compilation; (3.2/3)

- les fonctions inline ont quand même un linkage externe, ce
qui assure, entre autres, qu'il n'y a qu'une seule copie des
variables statiques qui y sont définies.

Si j'ai bon, alors c'est ce que je pensais depuis des années.
J'en serai heureux, car je n'aurai pas à changer ce que j'ai
écrit dans mes livres. J'aimerais juste effacer mes messages
récents sur fclc++ :-)

Il faudra bien que je trouve la discussion (j'imagine sur
clc++m ou csc++) qui m'a fait penser qu'il y avait une
subtilité que je ne connaissais pas. C'est intriguant, je
n'ai certainement pas pris cette note pour rien, il fallait
que la conclusion vienne de quelqu'un d'important...

(Je suis désolé si j'ai, à mon tour, amené de la confusions sur
ce point pourtant assez simple. Merci Gabriel d'enlever toute
confusion dans ton prochain message !)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/



Avatar
Michel Michaud
Dans news:, Gabriel
"Michel Michaud" writes:
Je ne comprends pas pourquoi tu utilises un ton sarcastique au
lieu de clarifier le point en litige.


Je crois que j'ai clairifié le point.


Maintenant oui. Merci.

Comme je l'ai indiqué dans
les messages que tu as lus, j'ai l'impression qu'une discussion
sur un forum m'a laissé une impression fausse.


Oui, mais tu ne me dis pas grand chose à part que quelqu'un
aurait dit quelque chose, mais quoi exactement ?


Je ne sais plus et ça semble évident que c'était une erreur.
Je m'étais simplement mis une petite note sur un bout de
papier, pour reviser mes livres sur ce point l'été venu. Ça
ne sera pas nécessaire (pour ce point).

En lisant tes
trois messages, je ne suis toujours pas sûr... En particulier,
ceci me semble contradictoire avec le reste :


Hue???


Tu as répondu « ce n'est pas ce que dit la norme », après que
j'aie parlé de linkage externe, puis « ARM avait une règle différente
(celle que tu décris) ». J'imagine qu'une partie
de tes remarques répondait à Michaël ou encore que tu voulais
dire que la norme ne dit pas ça exactement de cette manière...
Ce n'est pas important. L'ensemble est clair maintenant.

[...]
Mais un des messages que tu as postés containait une erreur.
Si tu déclares une fonction (avec linkage externe) inline dans
le programme, alors toutes ses déclarations doivent contenir
inline.


Oui oui, on s'entend. J'ai écrit quelque chose qui me semble
maintenant aussi faux que je l'aurais cru il y a quelques
mois :-) Lorsque j'aurai un peu de temps, j'essaierai de
trouver ce qui m'a induit en erreur. (à suivre si je trouve)

- les fonctions inline ont quand même un linkage externe, ce
qui assure, entre autres, qu'il n'y a qu'une seule copie des
variables statiques qui y sont définies.


Inline n'affecte pas le linkage.


Exactement. Et c'est plus simple comme ça.

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


Avatar
Jean-Marc Bourguet
"Michel Michaud" writes:

Dans news:, Jean-Marc
"Michel Michaud" writes:

Je n'ai pas le temps de vérifier ce cas dans la
norme, mais à tout le moins, ceci devrait fonctionner :

// A.cpp
inline void A()
{}

// B.cpp
void A();

int main()
{
A();
}


Non. Il faut avoir une définition dans toute unité où la
fonction est utilisée (3.2/3).


C'est ce que je comprenais aussi jusqu'à récemment. Mais j'ai
pris une note disant que ce n'est pas le cas suite à une
discussion vue sur un forum (je n'ai pas noté la référence
exacte). Y aurait-il une correction à la norme (ou un DR) qui
vient changer ce qu'on peut lire à 3.2/3 ?

(ça me ferait plaisir de me tromper, car j'ai pris la note pour
dire que je devais corriger ce que mes livres indiquent !)


Je ne sais pas ce qui t'a induit en erreur, ni si la discussion avec
Gabriel a resolu ton probleme. Ma comprehension est
- il faut et il a toujours fallu avoir une definition dans toute
unite ou la fonction est utilisee
- d'apres l'ARM, c'etait de "static linkage", avec des consequences
potentielles (peut-etre pas toutes dans l'ARM) sur la recherche
des noms dans le cas des templates (ca c'est certain que ce n'etait
pas le cas dans l'ARM), l'ODR, les variables statitiques, les
tests d'egalite si on prend l'adresse de la fonction, j'en
oublie vraissemblablement
- d'apres la norme, c'est de "extern linkage", avec d'autres
consequences sur ces points.

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
kanze
Anthony Fleury wrote in message
news:<40acef68$0$21569$...
Michaël Delva wrote:

J'ai testé ;-)

Les implémentations des fonctions sont dans le CPP (Example d'une
fonction)

inline char Base64::Encode(unsigned char uc)
{


Une fonction inline voit sa portée limitée au fichier en cours, donc
il faut qu'elle soit définie dans le .h


Pas vraiment. Une fonction inline a les mêmes règles de visiblité que
n'importe quelle autre fonction. En revanche :

- si une fonction est déclarée inline, on a droit d'en fournir la
définition (l'implémentation) dans autant d'unité de compilation
qu'on veut,

- si une fonction est déclarée inline, il faut qu'il y en a une
définition dans chaque unité de compilation qui l'utilise, et

- si une fonction est déclarée inline dans une unité de compilation,
et non dans une autre, on a un comportement indéfini.

Dans son cas, son problème vient du troisième point -- la fonction n'est
déclarée inline que dans l'unité de compilation où elle a été définie.
Mais qu'il resoude ce problème (disons qu'en ajoutant inline à la
déclaration dans la classe), il tombera tout de suite sur le deuxième
point.

La solution préférée, au moins de moi, c'est de définir les fonctions
inline dans un fichier à part (type .ihh, mais ça n'a pas d'importance),
qui est include du fichier d'en-tête. De cette façon, toute unité de
compilation qui inclut la définition de la classe inclut automatiquement
la définition des fonctions inline, avec la declaration qu'elles soient
inline.

Mais enfin, la meilleur solution de toute, c'est de ne pas avoir de
fonctions inline de tout. Jusqu'au jour, évidemment, que le profiler te
dit autrement.

--
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
kanze
"Michel Michaud" wrote in message
news:<rI6rc.71670$...
Dans news:40acef68$0$21569$, Anthony
Michaël Delva wrote:

J'ai testé ;-)

Les implémentations des fonctions sont dans le CPP (Example d'une
fonction)

inline char Base64::Encode(unsigned char uc)
{


Une fonction inline voit sa portée limitée au fichier en cours, donc
il faut qu'elle soit définie dans le .h


Pas vraiment il me semble, en tout cas pas pour les fonctions libres
où le inline laisse le « external linkage »...

Mais comme ça ne fonctionne pas pour Michaël, soit ce n'est pas le cas
pour les fonctions membres, soit son compilateur n'est pas à jour. Je
n'ai pas le temps de vérifier ce cas dans la norme, mais à tout le
moins, ceci devrait fonctionner :

// A.cpp
inline void A()
{}

// B.cpp
void A();

int main()
{
A();
}

Évidemment, il est possible que le inline ne soit pas respecté au
niveau de la génération du code...


Selon la norme (§7.1.2/4) : « An inline function shall be defined in
every translation unit in which it is used and shall have exactly the
same definition in every case. If a funciton with external linkage is
declared inline in one translation uni, it shall be declared in line in
all translation units in which it appears; no diagnostic is required. »

Ton programme a un comportement indéfini (« no diagnostic is required »).

--
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
kanze
Gabriel Dos Reis wrote in message
news:...
Anthony Fleury writes:

[...]

| 3.2 point 3 : "An inline function shall be defined in every
| translation unit in which it is used"

| Pourquoi cette restriction ??

Il faut une exigence quelque part. Oui bien tu la mets sur
l'utilisateur ou bien tu la mets sur l'implémenteur (ou parfois les
deux). Cela demande plus d'infrastructure d'inliner trans uniter de
traduction que d'avoir le corps disponible dans chaque unité de
traduction.


Est-ce qu'il en faut plus que pour export ? Ou est-ce que les mêmes
méchanismes que pour export pourraient servir ?

Si tu demandes trop de travail aux implémenteurs, ils ne feront qu'à
leurs têtes et il peut arriver qu'ils fassent n'importe quoi.


Comme export ?

Et que tu n'aies pas la fonctionnalité que tu veux.


Comme export !

Alors, tu demandes un peu d'effort de la part de l'utilisateur.


Ou beaucoup, comme dans les alternatifs à export:-).

N'oublie pas, « inline » a été introduit en C with Classes vers 1981
avec l'exigence que ce soit utile ici et maintenant. 25 ans plus tard,
peu de progrès ont été faits :-(


Il y avait quand même une différence. Au moins jusqu'à l'ARM, les
fonctions inline non-membre étaient implicitement « static ». Donc, sans
linkage. Et la plupart (toutes ?) des implémentations traitaient des
fonctions membre de la même façon, bien que la notion d'une fonction
membre sans linkage était une aberration.

--
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
kanze
Gabriel Dos Reis wrote in message
news:...
"Michel Michaud" writes:

[...]

| > Dans la norme ok, mais dans la pratique je n'ai vu que des
| > compilateurs qui avaient un comportement qui faisait que inline
| > entrainait static, c'est à dire réduction de la portée de la
| > fonction.

| Ça fonctionne comme j'ai décrit avec VC 7.1...

oui mais non.

| C'est surprenant que ça ne fonctionne pas avec g++

Parce que g++ implémente ce qu'exige la norme sur ce point.


VC++ aussi. Son programme avait un comportement indéfini. Du coup,
quoique fasse le compilateur, c'est « ce qu'exige la norme ».

C'est effectivement étrange d'implémenter ce que la norme stipule,
d'ailleurs je ne comprends pas pourquoi on a une norme.


Je me pose bien la question parfois aussi.

--
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
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote in message
| news:...
| > Anthony Fleury writes:
|
| > [...]
|
| > | 3.2 point 3 : "An inline function shall be defined in every
| > | translation unit in which it is used"
|
| > | Pourquoi cette restriction ??
|
| > Il faut une exigence quelque part. Oui bien tu la mets sur
| > l'utilisateur ou bien tu la mets sur l'implémenteur (ou parfois les
| > deux). Cela demande plus d'infrastructure d'inliner trans uniter de
| > traduction que d'avoir le corps disponible dans chaque unité de
| > traduction.
|
| Est-ce qu'il en faut plus que pour export ?

Je ne crois pas qu'il en faudrait plus qu'export -- MS n'a pas export
mais j'ai entendu dire qu'il ferait maintenant de l'inlining intra
unité de traduction. GCC peut expérimentalement faire de l'inlining
trans unités de traduction (et des gens travaillent activement chez
Apple sur ça), et pourtant, GCC n'as pas encore les instructures en
place pour implémenter export.

| Ou est-ce que les mêmes
| méchanismes que pour export pourraient servir ?

Si, on a export oui, je crois que les mêmes infrastructures pourraient
servir (à moins que l'infrastructure soit *trop* « clerver » :-)).

| > Si tu demandes trop de travail aux implémenteurs, ils ne feront qu'à
| > leurs têtes et il peut arriver qu'ils fassent n'importe quoi.
|
| Comme export ?
|
| > Et que tu n'aies pas la fonctionnalité que tu veux.
|
| Comme export !

:-(. Ceux qui voulaient la compilation séparée ne voulaient
(probablement) pas export. Mais comme, c'était devenu un marchandage
et que la norme est un compromis, tout le monde est satisfait et
personne n'est content.

-- Gaby
1 2 3 4