C++ manque l'équivalent de PHP self
mot-clé qui est évalué au type de la classe englobante.
C'est assez facile de le simuler sur une base par classe :
struct Foo
{
typedef Foo self;
};
mais je devais écrire Foo
encore. Peut-être qu'un jour je me tromperai et causerai un bug silencieux.
Puis-je utiliser une combinaison de decltype
et amis pour que cela fonctionne de manière "autonome" ? J'ai déjà essayé ce qui suit mais this
n'est pas valable à cet endroit :
struct Foo
{
typedef decltype(*this) self;
};
// main.cpp:3:22: error: invalid use of 'this' at top level
// typedef decltype(*this) self;
(Je ne vais pas m'inquiéter de l'équivalent de static
qui fait la même chose mais avec une liaison tardive).
9 votes
this_t
serait probablement plus conforme à la dénomination normale du C++.3 votes
@BartekBanachewicz : ou ce_type
0 votes
Accepterez-vous aussi les réponses C++14 ? Cela pourrait fonctionner dans ce cas.
0 votes
Pouvez-vous donner un exemple où cela serait nécessaire ? Quel est le problème avec
this
?2 votes
@rwols : pour informations sur le type de produit à la portée de la définition de la classe, et pas seulement à l'implémentation non statique ? Par exemple, ce serait bien de pouvoir écrire ` public : treenode_type<ThisT> clone() const;` etc. Cela vous épargnerait parfois beaucoup de travail lorsque vous renommez les classes (et si vous ne pouvez pas les "refactorer" automatiquement).
2 votes
Même si vous avez réussi à créer le
typedef
comme vous le souhaitez, vous devrez toujours répéter le nom de la classe pour les constructeurs. Il n'y a pas d'alternative à cela.11 votes
@Praetorian, je ne me rappelle pas si c'était une proposition ou non, mais quelqu'un a suggéré
auto()
et~auto()
pour les ctors/dtors. C'est pour le moins intéressant. S'il est utilisé dans ce but, peut-êtretypedef auto self;
mais ça me semble un peu vague.2 votes
@Praetorian : Mais vous voyez une erreur de compilation solide et garantie si vous obtenez ceux mauvais.
0 votes
@rwols :
this
est une expression, pas un type, et il n'existe pas à l'intérieur destatic
les fonctions des membres.2 votes
Oh mon dtors/ctors comme
auto() ~auto()
semble si génial edit : à première vue en tout cas.12 votes
Honnêtement, si je devais suggérer une syntaxe pour rendre ceci possible, ce serait probablement
decltype(class)
peut-être avec undecltype(struct)
équivalent. C'est beaucoup plus clair queauto
dans un contexte spécifique et je ne vois aucun problème à ce qu'il s'intègre dans la langue en se basant surdecltype(auto)
.1 votes
+1 pour ça. Une utilisation comme
decltype(class)const&
peut commencer à sembler étrange, mais ce serait quand même une solution claire et succincte.11 votes
Comme vous voulez éviter les erreurs, vous pouvez mettre en place une fonction membre fictive avec static_assert, comme suit
void _check() { static_assert(std::is_same<self&, decltype(*this)>::value, "Correct your self type"); }
Cela ne fonctionne pas avec les modèles de classe, cependant...0 votes
@chris : Ouais, j'aime ça
2 votes
@chris
class
semble restrictive :decltype(typename)
est le type du type englobant ? Je suppose que les tableaux posent problème, car on ne connaît pas leur taille avant qu'ils ne soient terminés. Maisdecltype(typename)
dans le corps d'unenum
pourrait être utile. Je supposeclass
impliquerait que si vous l'utilisez dans un lambda à l'intérieur de l'élémentclass
il renverrait toujours leclass
? Est-ce que cela fonctionne dans les corps qui ne sont pas en ligne dans le fichierclass
définition ?0 votes
@Yakk, Points intéressants. Les deux méthodes fonctionnent pour moi. Je m'attendrais à ce que cela donne le type du foncteur lambda, oui, et que cela fonctionne dans plus que juste la définition de la classe si cela ne cause pas de problèmes imprévus. Une autre utilisation pratique pourrait être dans les définitions :
void decltype(typename)::foo() {}
1 votes
Le code est lu bien plus souvent qu'il n'est écrit, et les classes sont lues bien plus souvent qu'elles ne sont renommées. Si vous insister en ayant un
self
outhis_t
typedef (et il n'y a absolument aucune situation dans laquelle vous en avez besoin), alors vous devriez simplement l'écrire. Tout ce qui est suggéré ici crée BEAUCOUP plus de confusion que de clarté. Si vous voulez renommer une classe, pourquoi n'utilisez-vous pas find&replace ? Vous n'avez pas besoin d'utiliser replace all, utilisez simplement find next, replace, find next, replace, etc.3 votes
@MilesRout : Quel plaisir c'est ? !
0 votes
et causer un bug silencieux Vous allez certainement provoquer (très probablement) un bug bruyant.
0 votes
@PaulSanders : Si vous avez de la chance ! Ce dont vous devez vous inquiéter, ce sont les silencieux :) En particulier ces jours-ci où tout le monde est obsédé par
auto
et/ou la saisie en canard (ou, du moins, sa simulation) de sorte qu'il n'y a plus de diagnostic de point d'échec lorsque vous avez utilisé le mauvais type... vous devez juste espérer qu'à un moment donné, certaines signatures ne correspondront plus et que vous découvrirez finalement que vous avez fait une erreur l'année dernière.0 votes
Au lieu de decltype(typename) - pourquoi ne pas simplement decltype() ?
0 votes
@Pete Ça ne marche pas. est le principal défaut. Ce qui est
decltype()
?1 votes
@LightnessRacesinOrbit en regardant les commentaires, decltype(class) ou decltype(typename) ont été suggérés comme syntaxe future possible. Il me semble que l'utilisation d'une expression vide pour decltype serait tout aussi claire que decltype(typename) pour identifier le type de la portée englobante. Et non, cela ne passe pas par le compilateur aujourd'hui. Je me demande si cela vaut la peine de faire une proposition de syntaxe.
0 votes
@MilesRout, votre position "auto-invalidante", dure et dogmatique (avec ces majuscules et ces minuscules) n'a rien à voir avec la réalité. italiques et "absolus") passe (entre autres) complètement à côté d'un point crucial (pourtant explicitement écrit dans la question), à savoir : lire un cours (même si c'est beaucoup plus que l'écrire) ne permet pas d'y mettre des bogues.
0 votes
@Pete Oh je vois. Oui, ce serait bien en fait.
0 votes
Il y a eu un proposition pour avoir une syntaxe pour cela (et d'autres cas similaires), mais elle a été mise de côté alors que le travail sur une réflexion plus générale est en cours.
0 votes
"Différents noms ont été discutés, notamment decltype(class), typename(typename) namespace(namespace)" Ugh !