8
votes

Comment définir des amis pour les classes définies à l'intérieur de la classe de modèle

Supposons que j'ai la classe de modèle suivante qui définit une classe imbriquée:

template <typename T>
struct foo {
    struct bar {
        friend struct maybeChangeType<bar>;
    };
};


7 commentaires

Puisque vous savez déjà comment résoudre le problème de surcharge, voulez-vous simplifier votre question à la question de spécialisation?


Peut-être plus simple avec Modèle Struct MaybechangeType ...


@Barry Bonne idée, terminée.


@ Jarod42 pourriez-vous élaborer?


@Dyp lancer un argument dans maybechangeType () et ressemble à une réponse?


@Dyp je ne peux pas utiliser C ++ 14 pourtant (C ++ 11 est OK) et je suis sûr que vous proposez une variable de modèle là-bas ...


@RYAN: quelque chose comme Demo


3 Réponses :


1
votes

Si vous pouvez peut-être exporter le paramètre de modèle T dans bar , et si vous pouvez ajouter un autre paramètre de modèle (par défaut) à MayBechangeType , Vous pouvez essayer ceci: xxx


7 commentaires

Le à l'aide de type = t dans mon exemple ci-dessus était juste pour la brièveté. Dans la vie réelle, ce serait à l'aide de type = une autre classement . Je pourrais peut-être utiliser Sfinae pour essayer de sortir le typename de la classe ... laissez-moi jouer avec ça.


Si vous pouvez reconnaître les instances de bar par un type de membre, vous pouvez utiliser TOWTRUE :: Valeur comme activer_if Condition, où Modèle Struct TownTrue: STD :: TRUE_TYPE {}; .


Mais comment différencier la version Specialized enable_if de la valeur par défaut sans exposer les utilisateurs à ce type de déchirure?


@ Ex-Bart Je suggérerais d'utiliser un identifiant de type unique à la place; quelque chose comme struct foo_bar {}; à la portée des espaces de noms, alors à l'aide d'identificateur = foo_bar; dans chaque barre et requête activer_if_t :: Valeur>


@ Ex-Bart Je ne pense pas que cela fonctionne réellement. Il compile, mais il utilise FOO dans un contexte non déductible et n'a donc jamais été sélectionné.


@Ryan je ne vois rien au-dessus qui ne devrait pas travailler. Très peut-être, il y a une faute typographique ou une incohérence, mais la question est une cible en mouvement, de sorte que ce n'est pas surprenant.


@Ryan j'ai essayé quelques variations ici . Tous fonctionnaient avec g ++ 5.2.0 (ainsi qu'avec G ++ 4.9.2 sur ma machine), sauf lorsque j'ai essayé de définir TownTrue comme alias de type au lieu de la classe dérivée. Quel compilateur utilisez-vous?



3
votes

En tant que solution intrusive, il est possible d'utiliser des fonctions pour la programmation de type (métaprogrammation). Vous pouvez écrire la fonction de type comme une fonction d'ami: xxx

remplacer type_t avec n'importe quel type_t . Ce n'est pas nécessaire, mais parfois pratique, de définir cette fonction, par ex. pour les calculs dans des expressions constantes. Type_T peut être amélioré avec les opérateurs de comparaison, pour remplacer std :: is_same avec infixe A == B par exemple. Le type type_t est utilisé à la place de t directement pour deux raisons:

  1. pour une définition de maybechangeTypeyType_adl , il est nécessaire de Construire un objet du type de retour.
  2. Tous les types ne peuvent pas être renvoyés à partir d'une fonction. Par exemple. Types abstraits, types de fonctions, types de réseau. Ceux-ci peuvent toujours être utilisés comme Arguments de modèle.

    en C ++ 14, j'utiliserais des modèles de variables pour mettre en œuvre cette fonction: xxx

    si cela perd une partie de la symétrie ( Paramètre VS Type de retour).


    Dans tous les cas, vous pouvez interroger le type comme suit: xxx

    une fonction d'automne MayBechANgentType peut être fourni pour refléter le modèle principal de l'OP: xxx

    ou, vous spécialisez un modèle de classe maybechangetype Existence de la fonction maybechangeTypeyType_adl : xxx


0 commentaires

0
votes

Inspiré des réponses de @ Ex-Bart et @Dyp, j'ai pu proposer la solution C ++ 11 suivante: xxx

Il a l'avantage de ne pas exposer fin Les utilisateurs ou les implémentations de la classe à la magie noire --- utilisateurs utilisent simplement maybechangeType et les classes peuvent la spécialiser en fournissant simplement un type Typef autre_type . .


5 commentaires

Cela nécessite que chaque type pris en charge soit mis en une seule place - dans assistant - et en tant que tel ne pas bien échouer. Les solutions ADL, ou Sfinae, basées sur la base de l'assistance seront distribuées si nécessaire.


@Yakk je ne pense pas que je suis. Si t contient la classe ou Typedef autre_type alors ce qui précède le ramassera. Sinon, t sera utilisé à la place. Tant que T est défini avant que le maybechangetype est utilisé, cela devrait fonctionner. Et il est impossible d'utiliser MaybechangeType avec un type incomplet car STD :: Declval souffle.


Supposons que vous ayez un modèle struct bob {}; qui n'a pas de autre_type alias, et que vous voulez maybechangeType pour revenir < Code> t si t est un type intégral. Avec le système ci-dessus, de telles améliorations doivent être effectuées dans Struct Helper ou via la modification de MayBechangeType . Vous obtenez "détecter autre_type et l'utiliser si présent", mais c'est à ce sujet. Et il y a des moyens plus propres de le faire!


Je suis toujours intéressé par des moyens plus propres de faire des choses, mais pourriez-vous élaborer? Rien présenté ici jusqu'à présent me frappe comme une solution "propre". Pour la situation BOB que vous décrivez, je serais simplement spécialiser le modèle - - pas de désordre, pas de bruit. Fonctionne idéal pour STD :: Array, STD :: Paire, etc. En fait, c'est ce que je faisais avec tout mon code jusqu'à ce que je me rendais compte que je ne pouvais pas me spécialiser pour des cours nichées de classes de modèle intérieures ...


Can_apply ou l'équivalent STD: : Version expérimentale.