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

Recherche de noms de modeles dependante des arguments

6 réponses
Avatar
drkm
Bonjour

La recherche de noms de modèles n'est pas dépendante des arguments
d'instanciation. Il n'y a pas pour les modèles d'équivalent du Koenig
Lookup. J'ai pensé à cela en lisant un GotW sur les traits. Mettons
que l'on veuille spécialiser std::char_traits pour un type défini par
l'utilisateur :

namespace MonNS {
class MonChar {
// ...
} ;
}

namespace std {
template <>
class char_traits< ::MonNS::MonChar > {
// ...
} ;
}

C'est d'ailleurs, si je ne m'abuse, ce qui a motivé la permission de
modification de std::, pour des spécialisations sur des types définis
par l'utilisateur.

J'aurais pourtant apprécié quelque chose comme :

// En-tête standard.
namespace std {
template < ... >
class string {
// ...
// Utilisation : *pas* de spécification de portée.
char_traits< CharT >::... ;
// ...
} ;
}

// En-tête utilisateur.
namespace MonNS {
class MonChar {
// ...
} ;
template <>
class char_traits< MonChar > {
// ...
} ;
}

Cela me semble coller plus au concept d'interface de classe de
Sutter [*], « ce qui fait référence à et est livré avec la classe »,
en formalisant « est livré avec » par « fait partie du même espace de
noms ».

[*] Je suppose qu'il ne s'agit pas de la définition du seul
Sutter, mais c'est dans Exceptional C++ que je l'ai vu énoncé
pour la première fois.

Ce n'est certes pas aussi vital que le Koenig Lookup, mais j'aurais
trouvé cela agréable. Pensez-vous que cela pourait avoir sa place
dans la norme, ou quelque chose s'y oppose-t-il ?

--drkm

6 réponses

Avatar
Franck Branjonneau
drkm écrivait:

J'aurais pourtant apprécié quelque chose comme :

// En-tête standard.
namespace std {
template < ... >
class string {
// ...
// Utilisation : *pas* de spécification de portée.
char_traits< CharT >::... ;
// ...
} ;
}

// En-tête utilisateur.
namespace MonNS {
class MonChar {
// ...
} ;
template <>
class char_traits< MonChar > {
// ...
} ;
}

Cela me semble coller plus au concept d'interface de classe de
Sutter [*], « ce qui fait référence à et est livré avec la classe »,
en formalisant « est livré avec » par « fait partie du même espace de
noms ».


Tu as oublié que std::string est une instance de
std::basic_string< _Character, _Traits, _Allocator >.

Donc

namespace MonNS {

class MonChar {
// ...
};

template <>
class MonTrait {
// ...
};

typedef std::basic_string< MonChar, MonTraits > MaString;

}
--
Franck Branjonneau

Avatar
drkm
Franck Branjonneau writes:

Tu as oublié que std::string est une instance de
std::basic_string< _Character, _Traits, _Allocator >.


L'exemple était en effet mal choisi.

Mais si l'on se place du côté de la conception d'un modèle utilisant
une classe de traits, cela oblige à l'ajouter comme paramètre du
modèle. Même s'il s'agit d'une évolution du modèle et qu'il est déjà
utilisé par ailleurs.

Ce que je veux dire, c'est que lorsque l'on a une utilisation de
modèle comme ceci :

template < typename U >
class C {
// ...
MonTraits< U >::... ;
// ...
} ;

MonTraits doit appartenir à l'espace de noms courant. Si on veut le
spécialiser, il faut le faire dans cet espace de noms. Tandis que
dans :

template < typename U >
class C {
// ...
U u ;
maFonction( u ) ;
// ...
} ;

maFonction peut faire partie soit de l'espace de noms courant, soit de
celui dans lequel est défini le type de son argument (le type effectif
de U lors de l'instanciation).

Je trouve ces deux cas « similaires » (dans la manière dont la
recherche de noms devrait être menée), alors que l'un bénéficie du
Koenig Lookup, et l'autre pas.

Je me demande alors s'il y a des arguments plaidant dans le sens de
cette différence de recherche de nom, ou s'il s'agit juste d'un point
auquel personne n'a pensé.

--drkm

Avatar
Gabriel Dos Reis
drkm writes:

[...]

| // En-tête utilisateur.
| namespace MonNS {
| class MonChar {
| // ...
| } ;
| template <>
| class char_traits< MonChar > {
| // ...
| } ;
| }

En gros, tu veux une règle qui dit qu'on peut définir les
spécialisations de template n'importe où. Je croyais que les règles
étaient déjà compliquées.

| Cela me semble coller plus au concept d'interface de classe de
| Sutter [*], « ce qui fait référence à et est livré avec la classe »,
| en formalisant « est livré avec » par « fait partie du même espace de
| noms ».
|
| [*] Je suppose qu'il ne s'agit pas de la définition du seul
| Sutter, mais c'est dans Exceptional C++ que je l'ai vu énoncé
| pour la première fois.
|
| Ce n'est certes pas aussi vital que le Koenig Lookup, mais j'aurais
| trouvé cela agréable. Pensez-vous que cela pourait avoir sa place
| dans la norme, ou quelque chose s'y oppose-t-il ?

Source de maux de tête désagréables.

-- Gaby
Avatar
Gabriel Dos Reis
drkm writes:

[...]

| Je me demande alors s'il y a des arguments plaidant dans le sens de
| cette différence de recherche de nom, ou s'il s'agit juste d'un point
| auquel personne n'a pensé.

La recherche de nom dépendant des arguments, tel que nous la
connaissons aujourd'hui, est le fruit d'un long processus d'évolution
pour régler des problèmes de lookup. Je ne comprends pas très bien le
problème de lookup que tu veux régler ici.

-- Gaby
Avatar
darkman_spam
Gabriel Dos Reis wrote in :

En gros, tu veux une règle qui dit qu'on peut définir les
spécialisations de template n'importe où. Je croyais que les règles
étaient déjà compliquées.


Tu croyais bien.

[...]

Source de maux de tête désagréables.


Argument de poids. Je prend.

--drkm

Avatar
darkman_spam
Gabriel Dos Reis wrote in :

La recherche de nom dépendant des arguments, tel que nous la
connaissons aujourd'hui, est le fruit d'un long processus d'évolution
pour régler des problèmes de lookup. Je ne comprends pas très bien le
problème de lookup que tu veux régler ici.


Il n'y pas de problème réel. Je trouvais juste qu'il y avait des
similitudes dans les deux cas que j'ai donné, et qu'il aurait été
/agréable/ d'utiliser un pendant du Koenig Lookup pour les modèles.
Mais je ne vois pas de problème insoluble par ailleurs, c'était juste
par curiosité.

--drkm