Conditionnelle au moment de la compilation de l'inclusion/exclusion de code basé sur l'argument de modèle(s)?
De considérer les éléments suivants de la classe, à l'intérieur struct Y
être utilisé comme un type, par exemple. dans les modèles, plus tard:
template<int I>
class X{
template<class T1>
struct Y{};
template<class T1, class T2>
struct Y{};
};
Maintenant, cet exemple sera bien évidemment pas de la compilation, avec l'erreur que le deuxième X<I>::Y
a déjà été défini ou qu'elle a trop de paramètres du modèle.
J'aimerais résoudre que sans (très) partielle de la spécialisation, depuis le int I
paramètre n'est pas le seul et la position de celui-ci peut différer dans différents partielle des spécialisations (mon struct semble de plus comme cela, le ci-dessus est seulement pour des raisons de simplicité de la question), donc j'aimerais one class fits every I
solution.
Ma première pensée a été de toute évidence enable_if
, mais qui semble échouer sur moi, par exemple. J'obtiens toujours la même erreur:
//assuming C++11 support, else use boost
#include <type_traits>
template<int I>
class X{
template<class T1, class = std::enable_if<I==1>::type>
struct Y{};
template<class T1, class T2, class = std::enable_if<I==2>::type>
struct Y{};
};
Donc, depuis enable_if
échoue, j'espère qu'il y est un autre moyen d'atteindre les objectifs suivants moment de la compilation, de vérification:
template<int I>
class X{
__include_if(I == 1){
template<class T1>
struct Y{};
}
__include_if(I == 2){
template<class T1, class T2>
struct Y{};
}
};
Ce serait juste pour me sauver beaucoup de la duplication de code, mais je serais vraiment heureux si elle est en quelque sorte possible.
Edit: Malheureusement, je ne peux pas utiliser l'évidence: variadic templates, comme je suis à l'aide de Visual Studio 2010, de sorte que seul le C++0x choses qui est pris en charge là, je peux utiliser. :/
- +1. Question intéressante. Vais essayer d'y répondre après l'heure de bureau 😀
- Je suis en attente avec plaisir. 🙂 Ma ligne de pensée, c'est qu'il devrait être possible, car le compilateur sait tout ce qu'il faut savoir à la, eh bien, au moment de la compilation.
- Vous n'êtes autorisé à utiliser le C++0x feautures?
- désolé, il semble idiot, mais qu'est-ce de variadic templates ? Vous pouvez simplement static_assert la taille de l'emballage.
- Pas idiot, désolé de ne pas fournir des informations à l': ne Peut pas utiliser le C++0x du variadic templates de pourtant, comme je suis à l'aide de Visual Studio 2010. :/ J'espère vraiment que VC11, pour en ressortir aussitôt, comme ceux variadic templates sont tout simplement génial pour les choses comme cela et le mot de passe de l'idiome.
- Voir mon commentaire ci-dessus (putain de réponse unique notifications. :P).
- Vous êtes à défaut, dans le même piège que de nombreux nouveaux utilisateurs, et poser des questions sur la solution plutôt que du problème. Qu'est-ce que vous essayez de résoudre? Comment est cette classe à être utilisé: permettre à un couple de cas d'utilisation exemples de la façon dont la classe est à être utilisé, et pourquoi qui nécessite l'utilisation d'un intérieur de type (avez-vous envisagé de typetraits?) Qui va le rendre plus simple pour argumenter sur le potentiel des approches différentes.
- Dans le
enable_if
approche qu'il vous manque un couple de:
, j'espère que ce n'était pas la source de l'erreur - Oups, non, c'était juste moi de ne pas regarder tout en tapant un exemple dans la question.
- Mon intention est de faire d'un modèle de typedef, dans un non-C++0x façon, ou comme un général
rebind
structure comme connu de allocateurs. Mais la question va plus loin, comme en posant des questions sur la compilation conditionnelle basée sur le modèle args en général.
Vous devez vous connecter pour publier un commentaire.
Il y a deux problèmes ici:
enable_if
fonctionne avec spécialisation partielle, pas de primaire modèles.Réponse 1.
Comme vous l'avez suggéré dans le chat, une liste de modèles peuvent imiter les variadic paramètre pack.
Si vous vous retrouvez avec
next::next::next
ordures, il est facile d'écrire un metafunction, ou utilisez le Boost MPL.Réponse 2.
Les différents arité de modèles peuvent être nommés de la même façon mais restent toujours distinctes si elles sont imbriquées à l'intérieur du SFINAE-contrôlée type.
enable_if
y travaille parce que la Substitution de l'Échec n'Est Pas Une Erreur (SFINAE) au sein de la déduction. Primaire les modèles n'ont pas que des avantages de la substitution de l'échec est une erreur.Ici, vous allez:
http://ideone.com/AdEfl
Et le code:
Explication: c'est en fait une extension de la notion de spécialisation partielle, cependant la différence est que, plutôt que de se spécialiser dans
Test
, déléguer à une classe spécifique qui peut être spécialisé surI
seul. De cette façon, vous avez seulement besoin de définir des versions deinner
pour chaqueI
une fois. Puis de multiples spécialisations deTest
pouvez ré-utiliser. Leinner
titulaire est utilisé pour faire de latypedef
dans leTest
de la classe la plus facile à manipuler.EDIT: voici un cas de test qui montre ce qui se passe si vous passez dans le mauvais nombre d'arguments de modèle: http://ideone.com/QzgNP
template<int I>
.I
est délégué à laTraits
de classe, et l'Test
classe utilise que, dans votre réponse, vous parliez de la spécialiséeTest
(ouX
) pour chaqueI
l'OP n'est pas disposé à le faire.Pouvez-vous essayer ci-dessous (il n'est pas partielle de spécialisation):
Je doute si la réponse est aussi simple que cela !!
Edition (se moquant de spécialisation Partielle):
@Xeo, j'ai été en mesure de compiler code suivant et semble être fullfilling.
Ici, cependant, vous pouvez utiliser X<1> X<2> de façon interchangeable. Mais dans le plus grand exemple que vous avez mentionné, c'est sans importance. Encore si vous avez besoin, vous pouvez mettre vérifie
I = 1
etI = 2
.int I
n'est pas le seul paramètre du modèle, mais il existe d'autres. Je l'ai lié à Ideone pour un petit exemple de ce à quoi il ressemble vraiment, la structure a été abrutir pour des raisons de simplicité de la question.Comment de cette approche - http://sergey-miryanov.blogspot.com/2009/03/template-class-overriding.html? (désolé pour le russe)
Vous pouvez utiliser un méta-fonction (ici: inline
boost::mpl::if_c
, mais peut être arbitrairement complexe) pour sélectionner celui que vous voulez. Vous avez besoin d'un échafaudage pour être en mesure d'utiliser des constructeurs, cependant:Si il y a un problème avec les deux
YforIeq
N être instancié pour chaque X, alors vous pouvez essayer de les enveloppant comme une nullary méta fonction (quelque chose le long du cheminmpl::apply
n') et l'utilisationmpl::eval_if_c
.