Guillaume LEMAÎTRE wrote:Loïc Joly wrote:Guillaume LEMAÎTRE wrote:La surcharge du constructeur amènerait à une initialisation
dynamique et non statique.
Je ne vois pas pourquoi. Peux-tu expliciter ce que tu veux dire ?
à supposer que l'on ait en plus :
-->
class Biniou {
// ...
Biniou( const int p_a, const char p_b ) : a( p_a ), b( p_b ) {};
// ...
};
// alors la ligne devient
const Biniou wesh = Biniou( 5, 'c' );
<--
cette déclaration provoquera avant l'entrée dans le main l'appel au
constructeur que l'on vient de surcharger qui se chargera
d'initialiser l'instance 'wesh'. C'est-à-dire du temps de perdu à
initialiser un objet dont on pouvait connaître par avance le contenu
!
Ah, je crois voir enfin ce que tu entendais par dynamique (j'avais
confondu avec le dynamique de à new ou malloc).
Si c'est bien le cas, je me pose alors quelques questions :
- Est-ce important ? Je n'ai pas l'impression que le temps
d'initialisation de quelques constantes soit en général un problème en
terme de performances.
- Un bon compilateur n'aurait-il pas le droit d'initialiser l'objet
wesh à la compilation ? Voire même de supprimer toute référence à wesh
du programme final et de remplacer tous les wesh.get_a() par 5 (puis
de continuer éventuellement à optimiser). Je n'ai rien vu dans la
norme qui semble empêcher ça (mais si je commence à savoir m'y
retrouver pour voir si quelquechose existe, je suis encore loin de la
connaître assez pour savoir qu'une chose n'existe pas), mais est-ce à
la portée des compilateurs actuels.
En particulier (3.6.2.2) :An implementation is permitted to perform the initialization of an
object of namespace scope with static storage duration as a static
initialization even if such initialization is not required to be
done statically, provided that the dynamic version of the
initialization does not change the value of any other object of
namespace scope with static storage duration prior to its
initialization, and
- the static version of the initialization produces the same value
in the initialized object as would be produced by the dynamic
initialization if all objects not required to be initialized
statically were initialized dynamically.
- Si vraiment c'est important, si la classe Biniou est un aggregate,
une écriture comme celle que tu as écrit au début est possible et
t'assure d'une initialisation pendant la phase statique (8.5.1.14).
When an aggregate with static storage duration is initialized with a
braceenclosed initializerlist, if all the member initializer
expressions are constant expressions, and the aggregate is a POD
type, the initialization shall be done during the static phase of
initialization (3.6.2); otherwise, it is unspecified whether the
initialization of members with constant expressions takes place
during the static phase or during the dynamic phase of
initialization.
Guillaume LEMAÎTRE wrote:
Loïc Joly wrote:
Guillaume LEMAÎTRE wrote:
La surcharge du constructeur amènerait à une initialisation
dynamique et non statique.
Je ne vois pas pourquoi. Peux-tu expliciter ce que tu veux dire ?
à supposer que l'on ait en plus :
-->
class Biniou {
// ...
Biniou( const int p_a, const char p_b ) : a( p_a ), b( p_b ) {};
// ...
};
// alors la ligne devient
const Biniou wesh = Biniou( 5, 'c' );
<--
cette déclaration provoquera avant l'entrée dans le main l'appel au
constructeur que l'on vient de surcharger qui se chargera
d'initialiser l'instance 'wesh'. C'est-à-dire du temps de perdu à
initialiser un objet dont on pouvait connaître par avance le contenu
!
Ah, je crois voir enfin ce que tu entendais par dynamique (j'avais
confondu avec le dynamique de à new ou malloc).
Si c'est bien le cas, je me pose alors quelques questions :
- Est-ce important ? Je n'ai pas l'impression que le temps
d'initialisation de quelques constantes soit en général un problème en
terme de performances.
- Un bon compilateur n'aurait-il pas le droit d'initialiser l'objet
wesh à la compilation ? Voire même de supprimer toute référence à wesh
du programme final et de remplacer tous les wesh.get_a() par 5 (puis
de continuer éventuellement à optimiser). Je n'ai rien vu dans la
norme qui semble empêcher ça (mais si je commence à savoir m'y
retrouver pour voir si quelquechose existe, je suis encore loin de la
connaître assez pour savoir qu'une chose n'existe pas), mais est-ce à
la portée des compilateurs actuels.
En particulier (3.6.2.2) :
An implementation is permitted to perform the initialization of an
object of namespace scope with static storage duration as a static
initialization even if such initialization is not required to be
done statically, provided that the dynamic version of the
initialization does not change the value of any other object of
namespace scope with static storage duration prior to its
initialization, and
- the static version of the initialization produces the same value
in the initialized object as would be produced by the dynamic
initialization if all objects not required to be initialized
statically were initialized dynamically.
- Si vraiment c'est important, si la classe Biniou est un aggregate,
une écriture comme celle que tu as écrit au début est possible et
t'assure d'une initialisation pendant la phase statique (8.5.1.14).
When an aggregate with static storage duration is initialized with a
braceenclosed initializerlist, if all the member initializer
expressions are constant expressions, and the aggregate is a POD
type, the initialization shall be done during the static phase of
initialization (3.6.2); otherwise, it is unspecified whether the
initialization of members with constant expressions takes place
during the static phase or during the dynamic phase of
initialization.
Guillaume LEMAÎTRE wrote:Loïc Joly wrote:Guillaume LEMAÎTRE wrote:La surcharge du constructeur amènerait à une initialisation
dynamique et non statique.
Je ne vois pas pourquoi. Peux-tu expliciter ce que tu veux dire ?
à supposer que l'on ait en plus :
-->
class Biniou {
// ...
Biniou( const int p_a, const char p_b ) : a( p_a ), b( p_b ) {};
// ...
};
// alors la ligne devient
const Biniou wesh = Biniou( 5, 'c' );
<--
cette déclaration provoquera avant l'entrée dans le main l'appel au
constructeur que l'on vient de surcharger qui se chargera
d'initialiser l'instance 'wesh'. C'est-à-dire du temps de perdu à
initialiser un objet dont on pouvait connaître par avance le contenu
!
Ah, je crois voir enfin ce que tu entendais par dynamique (j'avais
confondu avec le dynamique de à new ou malloc).
Si c'est bien le cas, je me pose alors quelques questions :
- Est-ce important ? Je n'ai pas l'impression que le temps
d'initialisation de quelques constantes soit en général un problème en
terme de performances.
- Un bon compilateur n'aurait-il pas le droit d'initialiser l'objet
wesh à la compilation ? Voire même de supprimer toute référence à wesh
du programme final et de remplacer tous les wesh.get_a() par 5 (puis
de continuer éventuellement à optimiser). Je n'ai rien vu dans la
norme qui semble empêcher ça (mais si je commence à savoir m'y
retrouver pour voir si quelquechose existe, je suis encore loin de la
connaître assez pour savoir qu'une chose n'existe pas), mais est-ce à
la portée des compilateurs actuels.
En particulier (3.6.2.2) :An implementation is permitted to perform the initialization of an
object of namespace scope with static storage duration as a static
initialization even if such initialization is not required to be
done statically, provided that the dynamic version of the
initialization does not change the value of any other object of
namespace scope with static storage duration prior to its
initialization, and
- the static version of the initialization produces the same value
in the initialized object as would be produced by the dynamic
initialization if all objects not required to be initialized
statically were initialized dynamically.
- Si vraiment c'est important, si la classe Biniou est un aggregate,
une écriture comme celle que tu as écrit au début est possible et
t'assure d'une initialisation pendant la phase statique (8.5.1.14).
When an aggregate with static storage duration is initialized with a
braceenclosed initializerlist, if all the member initializer
expressions are constant expressions, and the aggregate is a POD
type, the initialization shall be done during the static phase of
initialization (3.6.2); otherwise, it is unspecified whether the
initialization of members with constant expressions takes place
during the static phase or during the dynamic phase of
initialization.
Guillaume LEMAÎTRE wrote:En tout cas, merci d'avoir pris mon cas en considération !
Euh, tu n'a pas répondu sur ce que tu pensais de faire de ta classe un
aggregate, afin de pouvoir l'initialiser comme en C...
Guillaume LEMAÎTRE wrote:
En tout cas, merci d'avoir pris mon cas en considération !
Euh, tu n'a pas répondu sur ce que tu pensais de faire de ta classe un
aggregate, afin de pouvoir l'initialiser comme en C...
Guillaume LEMAÎTRE wrote:En tout cas, merci d'avoir pris mon cas en considération !
Euh, tu n'a pas répondu sur ce que tu pensais de faire de ta classe un
aggregate, afin de pouvoir l'initialiser comme en C...
Guillaume LEMAÎTRE wrote in message
news:<brne5n$ffh$...J'aimerai savoir s'il existe des stratagèmes pour qu'une instance
constante d'une classe soit directement initialisée dans l'exécutable
et ne nécessite pas l'appel de constructeurs globaux.Pour faire plus clair :-->class Biniou {
int a;
char b;public :const int get_a( void ) const { return a; };
const char get_b( void ) const { return b; };int & set_a( void ) { return a; };
char & set_b( void ) { return b; };
};// ligne invalide, mais qui veut bien dire ce qu'elle veut direconst Biniou wesh = { 5, 'c' };<--
Pourquoi c'est invalide ? Elle a l'air parfaitement valide pour moi.
J'utilise parfois quelque chose du genre :
template< typename T1, typename T2 >
struct pod_pair
{
T1 first ;
T2 second ;
operator std::pair< T1, T2 >()
{
return std::pair< T1, T2 >( first, second ) ;
}
} ;
exprès pour me permettre d'écrire par exemple :
pod_pair< char const*, int > const
initTable[] > {
{ "toto", 42 },
{ "titi", 34 },
// ...
} ;
std::map< std::string, int >
map( begin( initTable ), end( initTable ) ) ;
La plupart du temps, le but n'est pas tant d'éviter l'initialisation
dynamique, mais de facilité l'écriture, mais si les deux éléments du
pod_pair sont bien POD eux-même, l'initialisation en est bien statique.
Aujourd'hui j'en suis réduit à patcher la section 'data' de
l'exécutable pour réaliser mes initialisations, ce qui est efficace
mais peu propre... Donc si l'un d'entre vous a une idée, elle est la
bienvenue
Pour l'instant, je ne vois pas où est le problème. Une classe serait
initialisée statiquement si son constructeur est trivial, et que les
initialisations sont tous des expressions constantes. Le constructeur
est trivial s'il n'est pas déclaré par le programmeur, et
- la classe n'a pas de fonctions virtuelles ni de classes de base
virtuelle,
- toutes les classes de bases ont des constructeurs triviaux, et
- tous les membres données non-statiques qui ont un type de classe ont
des constructeurs triviaux.
(Note bien que dans mon pod_pair, si j'instancie avec le premier type
std::string à la place de char const*, l'initialisation ne serait plus
statique, mais dynamique.)
PS: les initalisations peuvent être citiques dans le cas de programmes
temps-réel embarqués.
Surtout si ces programmes sont en PROM, n'est-ce pas ?
En général, même dans le cas des programmes sur ordinateur général (PC,
Sun, etc.), l'initialisation statique a l'avantage de ne pas introduire
des dépendences dans l'ordre d'initialisation -- quoiqu'il arrive, je
sais que ma variable « initTable » ci-dessus serait initialisée avant
son utilisation.
Guillaume LEMAÎTRE <zarmalala@biniou.org> wrote in message
news:<brne5n$ffh$1@news-reader5.wanadoo.fr>...
J'aimerai savoir s'il existe des stratagèmes pour qu'une instance
constante d'une classe soit directement initialisée dans l'exécutable
et ne nécessite pas l'appel de constructeurs globaux.
Pour faire plus clair :
-->
class Biniou {
int a;
char b;
public :
const int get_a( void ) const { return a; };
const char get_b( void ) const { return b; };
int & set_a( void ) { return a; };
char & set_b( void ) { return b; };
};
// ligne invalide, mais qui veut bien dire ce qu'elle veut dire
const Biniou wesh = { 5, 'c' };
<--
Pourquoi c'est invalide ? Elle a l'air parfaitement valide pour moi.
J'utilise parfois quelque chose du genre :
template< typename T1, typename T2 >
struct pod_pair
{
T1 first ;
T2 second ;
operator std::pair< T1, T2 >()
{
return std::pair< T1, T2 >( first, second ) ;
}
} ;
exprès pour me permettre d'écrire par exemple :
pod_pair< char const*, int > const
initTable[] > {
{ "toto", 42 },
{ "titi", 34 },
// ...
} ;
std::map< std::string, int >
map( begin( initTable ), end( initTable ) ) ;
La plupart du temps, le but n'est pas tant d'éviter l'initialisation
dynamique, mais de facilité l'écriture, mais si les deux éléments du
pod_pair sont bien POD eux-même, l'initialisation en est bien statique.
Aujourd'hui j'en suis réduit à patcher la section 'data' de
l'exécutable pour réaliser mes initialisations, ce qui est efficace
mais peu propre... Donc si l'un d'entre vous a une idée, elle est la
bienvenue
Pour l'instant, je ne vois pas où est le problème. Une classe serait
initialisée statiquement si son constructeur est trivial, et que les
initialisations sont tous des expressions constantes. Le constructeur
est trivial s'il n'est pas déclaré par le programmeur, et
- la classe n'a pas de fonctions virtuelles ni de classes de base
virtuelle,
- toutes les classes de bases ont des constructeurs triviaux, et
- tous les membres données non-statiques qui ont un type de classe ont
des constructeurs triviaux.
(Note bien que dans mon pod_pair, si j'instancie avec le premier type
std::string à la place de char const*, l'initialisation ne serait plus
statique, mais dynamique.)
PS: les initalisations peuvent être citiques dans le cas de programmes
temps-réel embarqués.
Surtout si ces programmes sont en PROM, n'est-ce pas ?
En général, même dans le cas des programmes sur ordinateur général (PC,
Sun, etc.), l'initialisation statique a l'avantage de ne pas introduire
des dépendences dans l'ordre d'initialisation -- quoiqu'il arrive, je
sais que ma variable « initTable » ci-dessus serait initialisée avant
son utilisation.
Guillaume LEMAÎTRE wrote in message
news:<brne5n$ffh$...J'aimerai savoir s'il existe des stratagèmes pour qu'une instance
constante d'une classe soit directement initialisée dans l'exécutable
et ne nécessite pas l'appel de constructeurs globaux.Pour faire plus clair :-->class Biniou {
int a;
char b;public :const int get_a( void ) const { return a; };
const char get_b( void ) const { return b; };int & set_a( void ) { return a; };
char & set_b( void ) { return b; };
};// ligne invalide, mais qui veut bien dire ce qu'elle veut direconst Biniou wesh = { 5, 'c' };<--
Pourquoi c'est invalide ? Elle a l'air parfaitement valide pour moi.
J'utilise parfois quelque chose du genre :
template< typename T1, typename T2 >
struct pod_pair
{
T1 first ;
T2 second ;
operator std::pair< T1, T2 >()
{
return std::pair< T1, T2 >( first, second ) ;
}
} ;
exprès pour me permettre d'écrire par exemple :
pod_pair< char const*, int > const
initTable[] > {
{ "toto", 42 },
{ "titi", 34 },
// ...
} ;
std::map< std::string, int >
map( begin( initTable ), end( initTable ) ) ;
La plupart du temps, le but n'est pas tant d'éviter l'initialisation
dynamique, mais de facilité l'écriture, mais si les deux éléments du
pod_pair sont bien POD eux-même, l'initialisation en est bien statique.
Aujourd'hui j'en suis réduit à patcher la section 'data' de
l'exécutable pour réaliser mes initialisations, ce qui est efficace
mais peu propre... Donc si l'un d'entre vous a une idée, elle est la
bienvenue
Pour l'instant, je ne vois pas où est le problème. Une classe serait
initialisée statiquement si son constructeur est trivial, et que les
initialisations sont tous des expressions constantes. Le constructeur
est trivial s'il n'est pas déclaré par le programmeur, et
- la classe n'a pas de fonctions virtuelles ni de classes de base
virtuelle,
- toutes les classes de bases ont des constructeurs triviaux, et
- tous les membres données non-statiques qui ont un type de classe ont
des constructeurs triviaux.
(Note bien que dans mon pod_pair, si j'instancie avec le premier type
std::string à la place de char const*, l'initialisation ne serait plus
statique, mais dynamique.)
PS: les initalisations peuvent être citiques dans le cas de programmes
temps-réel embarqués.
Surtout si ces programmes sont en PROM, n'est-ce pas ?
En général, même dans le cas des programmes sur ordinateur général (PC,
Sun, etc.), l'initialisation statique a l'avantage de ne pas introduire
des dépendences dans l'ordre d'initialisation -- quoiqu'il arrive, je
sais que ma variable « initTable » ci-dessus serait initialisée avant
son utilisation.
wrote:Guillaume LEMAÎTRE wrote in message
news:<brne5n$ffh$...
Pourquoi c'est invalide ? Elle a l'air parfaitement valide pour moi.
J'utilise parfois quelque chose du genre :
template< typename T1, typename T2 >
struct pod_pair
{
T1 first ;
T2 second ;
operator std::pair< T1, T2 >()
{
return std::pair< T1, T2 >( first, second ) ;
}
} ;
exprès pour me permettre d'écrire par exemple :
pod_pair< char const*, int > const
initTable[] > > {
{ "toto", 42 },
{ "titi", 34 },
// ...
} ;
std::map< std::string, int >
map( begin( initTable ), end( initTable ) ) ;
La différence à mes yeux est que ta structure pod_pair n'a pas de
notion d'interface, c'est-à-dire que tout est visible (et
particulièrement les champs).
Dans ma classe Biniou, mes champs sont privés et je fournis des
accesseurs sur ceux-ci. J'ai qualifié ma ligne d'initialisation
invalide car il me semblerait choquant de pouvoir initialiser une
classe à partir d'un aggrégat alors que je ne suis pas sensé connaître
son implémentation mais seulement son interface. Et d'ailleurs, cela
choque gcc également (depuis de très vieilles versions). L'exemple que
tu me fournis fonctionne, et cela ne me choque guère car tout est
visible.
La plupart du temps, le but n'est pas tant d'éviter l'initialisation
dynamique, mais de facilité l'écriture, mais si les deux éléments du
pod_pair sont bien POD eux-même, l'initialisation en est bien
statique.
tout à fait.
Aujourd'hui j'en suis réduit à patcher la section 'data' de
l'exécutable pour réaliser mes initialisations, ce qui est efficace
mais peu propre... Donc si l'un d'entre vous a une idée, elle est la
bienvenue
Pour l'instant, je ne vois pas où est le problème. Une classe serait
initialisée statiquement si son constructeur est trivial, et que les
initialisations sont tous des expressions constantes. Le
constructeur est trivial s'il n'est pas déclaré par le programmeur,
et
- la classe n'a pas de fonctions virtuelles ni de classes de base
virtuelle,
- toutes les classes de bases ont des constructeurs triviaux, et
- tous les membres données non-statiques qui ont un type de classe ont
des constructeurs triviaux.
(Note bien que dans mon pod_pair, si j'instancie avec le premier
type std::string à la place de char const*, l'initialisation ne
serait plus statique, mais dynamique.)
tout à fait d'accord. Néanmoins je tiens à replacer le contexte : nous
sommes dans un contexte industriel. Vu l'extrait cité par Loïc, un bon
compilateur pourrait mener à bien toutes ces optimisations en
analysant l'ensemble des types dépendants et en générant donc ma
constante en section 'read-only data'. Mais tous les compilateurs ne
sont pas de bons compilateurs, loin s'en faut (malheureusement).
PS: les initalisations peuvent être citiques dans le cas de
programmes temps-réel embarqués.
Surtout si ces programmes sont en PROM, n'est-ce pas ?
Exactement. Aujourd'hui mes constantes sont initialisées
dynamiquement, et sont donc de fait dupliquées entre la ROM et la RAM
pour être initialisées, ce qui est ridicule !
De plus, le compilateur utilisé génère plus de code pour initialiser
une constante que de données constantes servant à cette
initialisation. Par exemple, une constante de 3ko théoriquement finit
par occuper 5ko de code et 3ko de données ! Et il paraît a priori
inutile de devoir exécuter ces 5ko de code puisque l'état de ma
constante *devrait* être connu statiquement (et malheureusement, je
suis loin de n'avoir qu'une seule constante à gérer...)
En général, même dans le cas des programmes sur ordinateur général
(PC, Sun, etc.), l'initialisation statique a l'avantage de ne pas
introduire des dépendences dans l'ordre d'initialisation --
quoiqu'il arrive, je sais que ma variable « initTable » ci-dessus
serait initialisée avant son utilisation.
La gestion de l'ordre des ctors est également problématique sur cette
application, tu fais bien de le souligner :)
kanze@gabi-soft.fr wrote:
Guillaume LEMAÎTRE <zarmalala@biniou.org> wrote in message
news:<brne5n$ffh$1@news-reader5.wanadoo.fr>...
Pourquoi c'est invalide ? Elle a l'air parfaitement valide pour moi.
J'utilise parfois quelque chose du genre :
template< typename T1, typename T2 >
struct pod_pair
{
T1 first ;
T2 second ;
operator std::pair< T1, T2 >()
{
return std::pair< T1, T2 >( first, second ) ;
}
} ;
exprès pour me permettre d'écrire par exemple :
pod_pair< char const*, int > const
initTable[] > > {
{ "toto", 42 },
{ "titi", 34 },
// ...
} ;
std::map< std::string, int >
map( begin( initTable ), end( initTable ) ) ;
La différence à mes yeux est que ta structure pod_pair n'a pas de
notion d'interface, c'est-à-dire que tout est visible (et
particulièrement les champs).
Dans ma classe Biniou, mes champs sont privés et je fournis des
accesseurs sur ceux-ci. J'ai qualifié ma ligne d'initialisation
invalide car il me semblerait choquant de pouvoir initialiser une
classe à partir d'un aggrégat alors que je ne suis pas sensé connaître
son implémentation mais seulement son interface. Et d'ailleurs, cela
choque gcc également (depuis de très vieilles versions). L'exemple que
tu me fournis fonctionne, et cela ne me choque guère car tout est
visible.
La plupart du temps, le but n'est pas tant d'éviter l'initialisation
dynamique, mais de facilité l'écriture, mais si les deux éléments du
pod_pair sont bien POD eux-même, l'initialisation en est bien
statique.
tout à fait.
Aujourd'hui j'en suis réduit à patcher la section 'data' de
l'exécutable pour réaliser mes initialisations, ce qui est efficace
mais peu propre... Donc si l'un d'entre vous a une idée, elle est la
bienvenue
Pour l'instant, je ne vois pas où est le problème. Une classe serait
initialisée statiquement si son constructeur est trivial, et que les
initialisations sont tous des expressions constantes. Le
constructeur est trivial s'il n'est pas déclaré par le programmeur,
et
- la classe n'a pas de fonctions virtuelles ni de classes de base
virtuelle,
- toutes les classes de bases ont des constructeurs triviaux, et
- tous les membres données non-statiques qui ont un type de classe ont
des constructeurs triviaux.
(Note bien que dans mon pod_pair, si j'instancie avec le premier
type std::string à la place de char const*, l'initialisation ne
serait plus statique, mais dynamique.)
tout à fait d'accord. Néanmoins je tiens à replacer le contexte : nous
sommes dans un contexte industriel. Vu l'extrait cité par Loïc, un bon
compilateur pourrait mener à bien toutes ces optimisations en
analysant l'ensemble des types dépendants et en générant donc ma
constante en section 'read-only data'. Mais tous les compilateurs ne
sont pas de bons compilateurs, loin s'en faut (malheureusement).
PS: les initalisations peuvent être citiques dans le cas de
programmes temps-réel embarqués.
Surtout si ces programmes sont en PROM, n'est-ce pas ?
Exactement. Aujourd'hui mes constantes sont initialisées
dynamiquement, et sont donc de fait dupliquées entre la ROM et la RAM
pour être initialisées, ce qui est ridicule !
De plus, le compilateur utilisé génère plus de code pour initialiser
une constante que de données constantes servant à cette
initialisation. Par exemple, une constante de 3ko théoriquement finit
par occuper 5ko de code et 3ko de données ! Et il paraît a priori
inutile de devoir exécuter ces 5ko de code puisque l'état de ma
constante *devrait* être connu statiquement (et malheureusement, je
suis loin de n'avoir qu'une seule constante à gérer...)
En général, même dans le cas des programmes sur ordinateur général
(PC, Sun, etc.), l'initialisation statique a l'avantage de ne pas
introduire des dépendences dans l'ordre d'initialisation --
quoiqu'il arrive, je sais que ma variable « initTable » ci-dessus
serait initialisée avant son utilisation.
La gestion de l'ordre des ctors est également problématique sur cette
application, tu fais bien de le souligner :)
wrote:Guillaume LEMAÎTRE wrote in message
news:<brne5n$ffh$...
Pourquoi c'est invalide ? Elle a l'air parfaitement valide pour moi.
J'utilise parfois quelque chose du genre :
template< typename T1, typename T2 >
struct pod_pair
{
T1 first ;
T2 second ;
operator std::pair< T1, T2 >()
{
return std::pair< T1, T2 >( first, second ) ;
}
} ;
exprès pour me permettre d'écrire par exemple :
pod_pair< char const*, int > const
initTable[] > > {
{ "toto", 42 },
{ "titi", 34 },
// ...
} ;
std::map< std::string, int >
map( begin( initTable ), end( initTable ) ) ;
La différence à mes yeux est que ta structure pod_pair n'a pas de
notion d'interface, c'est-à-dire que tout est visible (et
particulièrement les champs).
Dans ma classe Biniou, mes champs sont privés et je fournis des
accesseurs sur ceux-ci. J'ai qualifié ma ligne d'initialisation
invalide car il me semblerait choquant de pouvoir initialiser une
classe à partir d'un aggrégat alors que je ne suis pas sensé connaître
son implémentation mais seulement son interface. Et d'ailleurs, cela
choque gcc également (depuis de très vieilles versions). L'exemple que
tu me fournis fonctionne, et cela ne me choque guère car tout est
visible.
La plupart du temps, le but n'est pas tant d'éviter l'initialisation
dynamique, mais de facilité l'écriture, mais si les deux éléments du
pod_pair sont bien POD eux-même, l'initialisation en est bien
statique.
tout à fait.
Aujourd'hui j'en suis réduit à patcher la section 'data' de
l'exécutable pour réaliser mes initialisations, ce qui est efficace
mais peu propre... Donc si l'un d'entre vous a une idée, elle est la
bienvenue
Pour l'instant, je ne vois pas où est le problème. Une classe serait
initialisée statiquement si son constructeur est trivial, et que les
initialisations sont tous des expressions constantes. Le
constructeur est trivial s'il n'est pas déclaré par le programmeur,
et
- la classe n'a pas de fonctions virtuelles ni de classes de base
virtuelle,
- toutes les classes de bases ont des constructeurs triviaux, et
- tous les membres données non-statiques qui ont un type de classe ont
des constructeurs triviaux.
(Note bien que dans mon pod_pair, si j'instancie avec le premier
type std::string à la place de char const*, l'initialisation ne
serait plus statique, mais dynamique.)
tout à fait d'accord. Néanmoins je tiens à replacer le contexte : nous
sommes dans un contexte industriel. Vu l'extrait cité par Loïc, un bon
compilateur pourrait mener à bien toutes ces optimisations en
analysant l'ensemble des types dépendants et en générant donc ma
constante en section 'read-only data'. Mais tous les compilateurs ne
sont pas de bons compilateurs, loin s'en faut (malheureusement).
PS: les initalisations peuvent être citiques dans le cas de
programmes temps-réel embarqués.
Surtout si ces programmes sont en PROM, n'est-ce pas ?
Exactement. Aujourd'hui mes constantes sont initialisées
dynamiquement, et sont donc de fait dupliquées entre la ROM et la RAM
pour être initialisées, ce qui est ridicule !
De plus, le compilateur utilisé génère plus de code pour initialiser
une constante que de données constantes servant à cette
initialisation. Par exemple, une constante de 3ko théoriquement finit
par occuper 5ko de code et 3ko de données ! Et il paraît a priori
inutile de devoir exécuter ces 5ko de code puisque l'état de ma
constante *devrait* être connu statiquement (et malheureusement, je
suis loin de n'avoir qu'une seule constante à gérer...)
En général, même dans le cas des programmes sur ordinateur général
(PC, Sun, etc.), l'initialisation statique a l'avantage de ne pas
introduire des dépendences dans l'ordre d'initialisation --
quoiqu'il arrive, je sais que ma variable « initTable » ci-dessus
serait initialisée avant son utilisation.
La gestion de l'ordre des ctors est également problématique sur cette
application, tu fais bien de le souligner :)