Est-il possible d'écrire un modèle pour vérifier la fonction de l'existence?
Est-il possible d'écrire un modèle qui change de comportement en fonction de si un membre de la fonction est définie sur une classe?
Voici un exemple simple de ce que j'ai envie d'écrire:
template<class T>
std::string optionalToString(T* obj)
{
if (FUNCTION_EXISTS(T->toString))
return obj->toString();
else
return "toString not defined";
}
Donc, si class T
a toString()
défini, puis il l'utilise; sinon, il n'a pas. La partie magique que je ne sais pas comment faire, c'est la "FUNCTION_EXISTS".
Bien sûr, il va sans dire que le modèle de réponse(s) ci-dessous fonctionnent uniquement avec de la compilation de l'information en temps, c'est à dire T doit avoir toString. Si vous passez dans une sous-classe de T t définir toString, mais T n' pas, il vous sera dit toString n'est pas défini.
Possible en Double Comment faire pour vérifier si un nom de membre (variable ou fonction) existe dans une classe, avec ou sans spécification de type?, car il couvre plus large de problème avec C++03 C++1y.
Possible en Double Comment faire pour vérifier si un nom de membre (variable ou fonction) existe dans une classe, avec ou sans spécification de type?, car il couvre plus large de problème avec C++03 C++1y.
OriginalL'auteur andy | 2008-11-02
Vous devez vous connecter pour publier un commentaire.
Oui, avec SFINAE vous pouvez vérifier si une classe donnée ne fournir une certaine méthode. Voici le code de travail:
J'ai juste testé avec Linux et gcc 4.1/4.3. Je ne sais pas si c'est portable sur les autres plates-formes d'exécution des compilateurs différents.
Je doute qu'il existe sur terre une plate-forme avec le sizeof(char) == sizeof(long)
Je ne suis pas entièrement sûr, mais je ne pense pas que ce est portable. typeof est un GCC extension, cela ne fonctionnera pas sur d'autres compilateurs.
typeof n'est pas nécessaire - char[sizeof(&C::helloworld)] fonctionne aussi bien. Et pour éviter sizeof(long)==sizeof(char), l'utilisation d'un struct { char[2] };. Il doit avoir une taille >=2
Trivial, mais il m'a fallu un certain temps à comprendre: remplacer
typeof
pardecltype
lors de l'utilisation de C++0x, par exemple, via-std=c++0x.OriginalL'auteur Nicola Bonelli
Cette question est ancienne, mais avec le C++11 nous avons une nouvelle façon de vérifier une des fonctions de l'existence (ou l'existence d'un non-membre de type, vraiment), en s'appuyant sur SFINAE de nouveau:
Maintenant à quelques explications. Première chose, j'utilise expression SFINAE à exclure la
serialize(_imp)
fonctions de résolution de surcharge, si la première expression à l'intérieur dedecltype
n'est pas valide (aka, la fonction n'existe pas).La
void()
est utilisé pour faire le type de retour de toutes les fonctions devoid
.La
0
argument est utilisé pour préférer laos << obj
surcharge si les deux sont disponibles (littérale0
est de typeint
et le premier de surcharge est un meilleur match).Maintenant, vous voulez probablement un trait de vérifier si une fonction existe. Heureusement, il est facile d'écrire que. Notez, cependant, que vous devez écrire un trait vous pour chaque nom de fonction, vous voudrez peut-être.
Exemple vivant.
Et sur les explications. Tout d'abord,
sfinae_true
est un helper de type, et il revient au même que l'écriture dedecltype(void(std::declval<T>().stream(a0)), std::true_type{})
. L'avantage, c'est simplement que c'est plus court.Ensuite, le
struct has_stream : decltype(...)
hérite de soitstd::true_type
oustd::false_type
en fin de compte, selon que l'decltype
vérifier danstest_stream
échoue ou non.Dernier,
std::declval
vous donne une "valeur" de ce type de col, sans que vous ayez besoin de savoir comment vous pouvez construire. Notez que ceci n'est possible à l'intérieur d'un non évaluée contexte, commedecltype
,sizeof
et autres.Noter que
decltype
n'est pas forcément nécessaire, commesizeof
(et tous les contextes non évaluée) a obtenu cette amélioration. C'est juste quedecltype
offre déjà un type et en tant que telle est juste plus propre. Voici unsizeof
version de l'un des surcharges:La
int
etlong
paramètres sont encore là pour la même raison. Le tableau de pointeur est utilisé pour fournir un contexte oùsizeof
peut être utilisé.decltype
sursizeof
est que temporaire n'est pas introduite par spécialement conçu règles pour les appels de fonction (de sorte que vous n'avez pas à avoir les droits d'accès pour le destructeur de le type de retour et de ne pas provoquer une instanciation implicite si le type de retour est un modèle de classe d'instanciation).Microsoft n'a pas mis en œuvre l'Expression SFINAE en elle le compilateur C++ de encore. Viens de comprendre que je pourrais l'aider à sauver certaines personnes de temps, comme je l'ai été confondu pourquoi cela ne fonctionnait pas pour moi. Solution sympa même si, ne peuvent pas attendre pour l'utiliser dans Visual Studio!
Votre premier exemple, le lien est rompu
Il faut dire, que
static_assert(has_stream<X, char>() == true, "fail X");
de compiler et de ne pas affirmer parce que char est modulable à l'int, donc si ce comportement n'est pas voulu et veulent que tous les types d'argument match, je ne sais pas comment il peut en être atteint?Si vous aussi surpris que j'étais sur les deux arguments de decltype: decltype ne prend vraiment un; la virgule est un opérateur ici. Voir stackoverflow.com/questions/16044514/...
OriginalL'auteur Xeo
C++ permet SFINAE être utilisé pour cette (remarquez qu'avec C++11 caractéristiques c'est plus simple, car il prend en charge étendue SFINAE sur presque arbitraire expressions - le ci-dessous a été conçu pour fonctionner avec le C++03 compilateurs):
le modèle ci-dessus et macro tente d'instancier un modèle, en lui donnant une fonction de membre de type pointeur, et le véritable membre de pointeur de fonction. Si les types de pas, SFINAE cause le modèle pour être ignoré. Utilisation comme ceci:
Mais notez que vous ne peut pas simplement appeler que
toString
fonction que si la branche. depuis le compilateur de vérifier la validité dans les deux branches, qui serait un échec pour les cas, la fonction n'existent pas. Une façon est d'utiliser SFINAE une fois de plus (enable_if peut être obtenu à partir de boost trop):Avoir du plaisir à l'utiliser. L'avantage de cela est qu'il fonctionne aussi pour la surcharge de fonctions membres, et aussi pour les fonctions membres const (rappelez-vous à l'aide de
std::string(T::*)() const
que la fonction de membre de type pointeur à l'époque!).type_check
est utilisé pour s'assurer que les signatures d'accord exactement. Est-il un moyen de faire en sorte qu'il corresponde à la méthode, ce qui pourrait être appelé de la même manière qu'une méthode avec signatureSign
pourrait être appelé? (E. g. siSign
=std::string(T::*)()
, permettrestd::string T::toString(int default = 42, ...)
de match.)Je viens de chiffres quelque chose à propos de ce qui n'était pas immédiate et évidente pour moi, donc dans le cas où il aide les autres: chk n'est pas et n'a pas besoin d'être défini! L'opérateur sizeof détermine la taille de la sortie de chk sans chk jamais avoir à être appelé.
Oui,
T
ne doit pas être un type primitif, parce que le pointeur-à-méthode-de-T de la déclaration n'est pas soumis à SFINAE et d'erreur pour n'importe quel non-classe de T. de l'OMI, la solution la plus simple consiste à combiner avecis_class
vérifier à partir de boost.Comment puis-je faire ce travail si mon
toString
est basé sur un modèle de fonction?Est-ce (ou quelque chose d'équivalent) dans coup de pouce?
OriginalL'auteur Johannes Schaub - litb
Si cette question est de deux ans, je vais oser ajouter ma réponse. Nous espérons qu'il permettra de clarifier la précédente, sans contredit une excellente solution. J'ai pris la très utile réponses de Nicola Bonelli et Johannes Schaub et de les fusionner en une solution qui est, à mon humble avis, plus lisible, clair et ne nécessite pas l'
typeof
extension:Je l'ai vérifié avec gcc 4.1.2.
Le mérite en revient principalement à Nicola Bonelli et Johannes Schaub, afin de leur donner une voix si ma réponse vous aide 🙂
cette solution se cache toute la logique à l'intérieur, Konrad met de la charge de l'utilisateur. Bien que de courte et beaucoup plus lisible, Konrad solution nécessite un modèle de spécialisation pour chaque classe qui a
toString
. Si vous écrivez une bibliothèque générique, qui souhaite travailler avec toute la classe y (penser à quelque chose comme coup de pouce), puis demander à l'utilisateur de définir d'autres spécialisations de certains obscur modèles pourrait être inacceptable. Parfois, il est préférable d'écrire un très compliquée code de tenir le public interface aussi simple qu'il peut être.OriginalL'auteur FireAphis
C++20 -
requires
expressionsAvec C++20 venir des concepts et des outils tels que
demande
expressions qui sont un moyen intégré pour vérifier la fonction de l'existence. Avec tehm vous pouvez réécrire votreoptionalToString
fonction comme suit:Pré-C++20 - Détection toolkit
N4502 propose une détection de boîte à outils pour l'inclusion dans le C++17 de la bibliothèque standard qui peut résoudre le problème en quelque sorte dans une élégante manière. En outre, il vient d'être accepté dans la bibliothèque fondamentaux TS v2. Elle introduit certains metafunctions, y compris
std::is_detected
qui peut être utilisée facilement pour écrire le type ou la fonction de détection de metafunctions sur le dessus de cela. Voici comment vous pourriez l'utiliser:Noter que l'exemple ci-dessus n'est pas testée. La détection de la trousse à outils n'est pas disponible dans les bibliothèques standard, mais encore la proposition contient une mise en œuvre complète qui vous permet de copier facilement si vous en avez vraiment besoin. Il joue bien avec le C++17 fonctionnalité
if constexpr
:Coup de pouce.TTI
Encore un peu idiomatiques trousse d'outils pour effectuer une telle vérification - même si moins élégant - est Coup de pouce.TTI, introduit en Boost 1.54.0. Pour votre exemple, vous devez utiliser la macro
BOOST_TTI_HAS_MEMBER_FUNCTION
. Voici comment vous pourriez l'utiliser:Ensuite, vous pouvez utiliser le
bool
pour créer un SFINAE vérifier.Explication
La macro
BOOST_TTI_HAS_MEMBER_FUNCTION
génère le metafunctionhas_member_function_toString
qui prend les bagages de type comme premier paramètre du modèle. Le deuxième paramètre du modèle correspond au type de retour de la fonction membre, et les paramètres suivants correspondent aux types de la fonction paramètres. Le membrevalue
contienttrue
si la classeT
a une fonction membrestd::string toString()
.Sinon,
has_member_function_toString
peut prendre un membre de pointeur de fonction en tant que paramètre du modèle. Par conséquent, il est possible de remplacerhas_member_function_toString<T, std::string>::value
parhas_member_function_toString<std::string T::* ()>::value
.OriginalL'auteur Morwenn
C'est ce type de traits sont là. Malheureusement, ils doivent être définis manuellement. Dans votre cas, imaginez la suite:
vous devriez préférer enum pour les traits à la place des constantes statiques : "constante Statique membres sont lvalues,ce qui force le compilateur à instancier et d'allouer la définition du membre statique. En conséquence, le calcul n'est plus limité à une pure "au moment de la compilation" en vigueur".
"Les valeurs d'énumération ne sont pas lvalues(qui est,ils n'ont pas une adresse).Donc, quand vous les transmettre "par référence" non statique de la mémoire est utilisée. C'est presque exactement comme si vous êtes passés à la valeur calculée comme un littéral. Ces considérations nous poussent à utiliser des valeurs d'énumération" des Modèles C++: Le Guide Complet
Comptrol: non, le passage cité ne s'applique pas ici puisque de type entier constantes statiques sont un cas spécial! Ils se comportent exactement comme un enum ici et sont le moyen privilégié. L'ancien enum hack a été nécessaire sur les compilateurs qui ne suivent pas la norme C++.
Pate: Pas tout à fait. “utilisées dans le programme” ici, apparemment, est synonyme de “référence”. La vigueur de la lecture de ce passage, et celui mis en œuvre par tous les compilateurs C++, c'est que vous pouvez prendre le valeur d'une constante statique sans avoir besoin de les déclarer (la phrase précédente, dit ceci: “... le membre peut apparaître dans intégrale des expressions constantes ...”). Vous besoin de définir si vous prenez son adresse (explicitement via
&T::x
ou implicitement par le liant à une référence).OriginalL'auteur Konrad Rudolph
Une solution simple pour le C++11:
Mise à jour, 3 ans plus tard: (et ce n'est pas testée). Pour tester l'existence, je pense que cela va fonctionner:
bon point. J'ai mis à jour ma réponse. Je n'ai pas testé si
Dans le cas où il aide à quelqu'un d'autre, je ne pouvais pas faire ce travail sans
template<typename>
avant les variadic surcharge: il n'était pas considérée, aux fins de résolution.OriginalL'auteur Aaron McDaid
Bien, cette question a une longue liste de réponses déjà, mais je tiens à souligner le commentaire de Morwenn: il y a une proposition pour le C++17 qui le rend vraiment beaucoup plus simple. Voir N4502 pour plus de détails, mais comme un exemple considérons l'exemple suivant.
Cette partie est la partie constante, le mettre dans un en-tête.
puis il y a la partie variable, où vous indiquez ce que vous recherchez (un type, un type de membre, une fonction, une fonction de membre etc.). Dans le cas de l'OP:
L'exemple suivant, pris de N4502, montre une version plus élaborée de la sonde:
Par rapport aux autres implémentations décrit ci-dessus, c'est assez simple: une réduction de l'ensemble d'outils (
void_t
etdetect
) suffit, pas besoin de poilu macros. En outre, il a été signalé (voir N4502) qu'il est réellement plus efficace (au moment de la compilation compilateur et la consommation de mémoire) que les approches précédentes.Ici est un live exemple. Il fonctionne très bien avec Clang, mais malheureusement, les versions de GCC avant de 5.1 suivi une interprétation différente de la standard C++11 qui a causé
void_t
à ne pas fonctionner comme prévu. Yakk déjà fourni le travail autour de: utiliser la définition suivante devoid_t
(void_t dans la liste des paramètres de la marche, mais pas comme type de retour):Oui, bien sûr. Regardez attentivement les exemples: en gros, vous fournir une expression et de vérifier s'il est valide. Rien n'exige que cette expression n'être que sur un appel de fonction membre.
N4502 (open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf) est la voie de l'avenir... je cherchais un joli moyen de détection de choses sur les types et les N4502 est le chemin à parcourir.
OriginalL'auteur akim
C'est un C++11 solution pour le problème général si "Si j'ai fait X, serait-il compiler?"
Trait
has_to_string
tels quehas_to_string<T>::value
esttrue
si et seulement siT
a une méthode.toString
qui peuvent être invoquées avec 0 arguments dans ce contexte.Prochaine, j'aimerais utiliser la balise expédition:
qui tend à être plus facile à gérer que le complexe SFINAE expressions.
Vous pouvez écrire ces traits avec une macro si vous vous retrouver à faire beaucoup, mais ils sont relativement simples (quelques lignes) donc peut-être pas la peine:
ce que le ci-dessus n'est de créer une macro
MAKE_CODE_TRAIT
. Vous transmettre le nom de la caractéristique que vous voulez, et du code qui peut tester le typeT
. Donc:crée la au-dessus de traits de classe.
Que d'un côté, la technique ci-dessus est une partie de ce que MS appelle "expression SFINAE", et leur 2013 compilateur échoue assez dur.
Noter qu'en C++1y la syntaxe suivante est possible:
qui est une ligne de compilation conditionnelle branche d'abus de beaucoup de fonctionnalités C++. Cela est probablement pas la peine, que le bénéfice (de code inline) ne vaut pas le coût (de la prochaine à personne de comprendre comment ça fonctionne), mais l'existence de cette solution ci-dessus peuvent être d'intérêt.
J'aurais expérience: comment les modèles d'interagir avec le public/privé/protégé est un peu obscur pour moi. Il ne sera pas question d'où vous appelez
has_to_string
cependant.qu'il ne les manipulez pas... Peut-être avec le C++de 20 ans que...
mais vous savez, si regarder de l'autre côté... On peut atteindre des membres protégés de la classe Dérivée. Peut-être que si vous mettez tous ces trucs à l'INTÉRIEUR de la classe, et de convertir les structures de constexpr fonctions...
Ici, regarde ce coliru.stacked-crooked.com/a/ee94d16e7c07e093 j'ai juste ne peux pas le faire constexpr
OriginalL'auteur Yakk - Adam Nevraumont
Ici sont certains de l'utilisation des extraits de:
*Le courage pour tous ce sont plus bas
Vérifier membre
x
dans une classe donnée. Pourrait être var, func, de classe, de l'union, ou enum:Vérifier la fonction de membre de
void x()
:Vérifier la variable de membre
x
:Vérifier membre de la classe
x
:Vérifier membre de l'union
x
:Vérifier membre enum
x
:Vérifier pour toute fonction membre
x
indépendamment de la signature:OU
De détails et de base:
Macros (El Diablo!):
CREATE_MEMBER_CHECK:
CREATE_MEMBER_VAR_CHECK:
CREATE_MEMBER_FUNC_SIG_CHECK:
CREATE_MEMBER_CLASS_CHECK:
CREATE_MEMBER_UNION_CHECK:
CREATE_MEMBER_ENUM_CHECK:
CREATE_MEMBER_FUNC_CHECK:
CREATE_MEMBER_CHECKS:
sig_check<func_sig, &T::func_name>
pour libérer de la fonction de vérification :sig_check<func_sig, &func_name>
il ne parvient pas à construire avec "identificateur non déclaré" de mentionner le nom de la fonction, nous voulons vérifier ? parce que je m'attends à ce SFINAE à faire PAS une erreur, c'est juste que pour les membres, pourquoi pas pour les fonctions libres ?Je suppose qu'il aurait quelque chose à voir avec le fait qu'une fonction n'est pas une classe ou structure. Cette technique de déduire la présence d'un membre est vraiment au centre sur le mécanisme d'héritage multiple en C++ forcer l'ambiguïté entre un stub de classe qui n'existe que dans le but d'accueillir le membre que vous vérifiez pour vs la classe que vous soyez à vérifier effectivement pour le membre. C'est une question intéressante mais, n'y avais pas pensé. Vous pouvez vérifier autour pour les autres C++11/14 états-vérifiez techniques, j'ai vu des choses intelligentes à la nouvelle norme.
Merci pour votre réponse, je pense que je pourrais avoir à vérifier plus en profondeur que les intel, vous donner à propos de l'héritage, parce que jusqu'à maintenant je ne vois pas de corrélation entre les tout simplement en s'appuyant sur SFINAE pour faire une expression qui ne serait pas correct exprimant l'accès à un membre d'un modèle type de paramètre, et l'héritage multiple. Mais je crois complètement qu'en C++, même lointains concepts peuvent saigner les uns sur les autres. Maintenant gratuitement les fonctions de cette question est intéressante: stackoverflow.com/questions/26744589 T. C réponse semble utiliser une astuce de la déclaration d'un mannequin afin d'éviter le "identificateur non déclaré"
OriginalL'auteur Brett Rossier
La norme C++ solution présentée ici par litb ne fonctionnera pas comme prévu si la méthode se trouve être définie dans une classe de base.
Pour une solution qui gère cette situation se référer à :
En Russe :
http://www.rsdn.ru/forum/message/2759773.1.aspx
De Traduction de l'anglais par Romain.Perepelitsa :
http://groups.google.com/group/comp.lang.c++.moderated/tree/browse_frm/thread/4f7c7a96f9afbe44/c95a7b4c645e449f?pli=1
Il est incroyablement intelligent. Cependant un problème avec ce solutiion est-ce que donne les erreurs de compilation si le type testée est celle qui ne peut pas être utilisée comme classe de base (par exemple, les types primitifs)
Dans Visual Studio, j'ai remarqué que si l'on travaille avec la méthode ayant pas d'arguments, d'une paire supplémentaire de licenciés ( ) doit être insérée à travers le argments à déduire( ) dans l'expression sizeof.
struct g { void f(); private: void f(int); };
parce que l'une des fonctions est privé (c'est parce que le code neusing g::f;
, ce qui en fait échouer si toutf
n'est pas accessible).OriginalL'auteur
MSVC a l' ___si il existe et __ _ _ _si non_existe des mots-clés (Doc). En collaboration avec la typeof-SFINAE approche de Nicola j'ai pu créer un chèque de GCC et de MSVC comme l'OP cherché.
Mise à jour: Source peut être trouvé Ici
OriginalL'auteur nob
J'ai écrit une réponse à cette question dans un autre thread que (contrairement aux solutions ci-dessus) vérifie également hérité des fonctions de membre:
SFINAE pour vérifier hérité des fonctions de membre du
Voici quelques exemple de cette solution:
Exemple1:
Nous sommes à la recherche d'une membre avec la signature suivante:
T::const_iterator begin() const
Veuillez noter qu'il vérifie bien que la constness de la méthode, et travaille avec des types primitifs. (Je veux dire
has_const_begin<int>::value
est faux et ne pas provoquer une erreur de compilation.)Exemple 2
Maintenant, nous sommes à la recherche de la signature:
void foo(MyClass&, unsigned)
Veuillez noter que MyClass n'a pas a être par défaut constructible ou pour satisfaire n'importe quel concept particulier. La technique fonctionne avec le modèle de membres.
Je suis avec impatience d'attente des opinions à ce sujet.
OriginalL'auteur kispaljr
Maintenant, c'était un nice peu casse-tête - bonne question!
Voici une alternative à Nicola Bonelli est la solution qui ne dépend pas de la non-standard
typeof
opérateur.Malheureusement, il ne fonctionne pas sur GCC (MinGW) 3.4.5 ou Numérique, Mars 8.42 n, mais il fonctionne sur toutes les versions de MSVC (y compris VC6) et sur Comeau C++.
Le plus de bloc de commentaire a les détails sur la façon dont il fonctionne (ou est censé fonctionner). Comme il le dit, je ne suis pas sûr de laquelle le comportement est conforme aux normes - je serais la bienvenue commentaire.
mise à jour - 7 Nov 2008:
On dirait bien que ce code est syntaxiquement correct, le comportement que MSVC et Comeau C++ show ne suivent pas la norme (grâce à Leon Timmermans et litb pour me pointer dans la bonne direction). Le C++03 standard dit ce qui suit:
Donc, il semble que lorsque MSVC ou Comeau envisager la
toString()
fonction de membre deT
d'effectuer la recherche d'un nom au site d'appel dansdoToString()
lorsque le modèle est instancié, c'est incorrect (même si c'est effectivement le comportement que je cherchais dans ce cas).Le comportement de GCC et de Numérique, Mars semble être correct dans les deux cas, la non-membre
toString()
fonction est liée à l'appel.Rats - j'ai pensé que je pourrais avoir trouvé une solution intelligente, au lieu de cela j'ai découvert un couple compilateur bugs...
Je sais que les commentaires ne donnent pas beaucoup de place, mais pourriez-vous point à l'information sur pourquoi il n'est pas conforme aux normes? (Je suis pas en train de dire - je suis curieux)
Mike B: que dit la norme en 3.10 p15: "Si un programme tente d'accéder à la valeur d'un objet à travers une lvalue d'autre que l'un des types suivants le comportement est indéfini" et de cette liste, en effet, ne comprennent pas le cas, vous ne.
je ne sais pas pourquoi il ne marche pas ajouter un autre commentaire de moi: votre toString appel est non qualifiés. donc, il faudra toujours faire appel à la fonction libre, et jamais dans la base, depuis le baseclass est personne à charge sur un modèle type de paramètre.
Merci pour les pointeurs. Je ne pense pas que 3.10 s'applique ici. L'appel à toString() à l'intérieur de doToString() n'est pas "accéder à la valeur d'un objet à travers une lvalue". Mais ton 2ème commentaire est correct. Je vais mettre à jour la réponse.
OriginalL'auteur Michael Burr
J'ai modifié la solution fournie dans https://stackoverflow.com/a/264088/2712152 pour le rendre un peu plus général. Aussi, puisqu'il n'utilise pas du tout de le nouveau C++11 fonctionnalités que l'on peut utiliser avec les anciens compilateurs et devrait également travailler avec msvc. Mais les compilateurs doivent permettre C99 pour utiliser cette car il utilise variadic macros.
La macro suivante peut être utilisée pour vérifier si une classe a un particulier typedef ou pas.
La macro suivante peut être utilisée pour vérifier si une classe a un membre en particulier ou non la fonction avec un nombre donné d'arguments.
Nous pouvons utiliser le ci-dessus 2 macros pour effectuer les contrôles pour has_typedef et has_mem_func:
HAS_MEM_FUNC( onNext, has_memberfn_onNext, void, Args... );
...template <typename V> struct Foo { void onNext(const V &); static_assert< has_memberfn_onNext<Foo<V>,const V &>::value, "API fail" ); };
OriginalL'auteur Shubham
Un exemple d'utilisation de SFINAE et le modèle partiel de la spécialisation, par la rédaction d'un
Has_foo
concept:OriginalL'auteur Paul Belanger
Étrange, personne n'a suggéré ce qui suit tour de nice, j'ai vu une fois sur ce site :
Vous devez vous assurer que T est une classe. Il semble que l'ambiguïté dans la recherche de foo est une substitution de l'échec. Je l'ai fait travailler sur gcc, vous ne savez pas si c'est standard.
OriginalL'auteur Alexandre C.
Le modèle générique qui peut être utilisé pour vérifier si une certaine "fonction" est pris en charge par le type:
Le modèle qui vérifie si il y a une méthode
foo
qui est compatible avec la signaturedouble(const char*)
Exemples
http://coliru.stacked-crooked.com/a/83c6a631ed42cea4
has_foo
dans le modèle d'appel deis_supported
. Ce que je voudrais, c'est d'appeler quelque chose comme:std::cout << is_supported<magic.foo(), struct1>::value << std::endl;
. La raison pour cela, je tiens à définir unhas_foo
pour chaque signature de fonction que je veux vérifier avant que je puisse vérifier pour la fonction?OriginalL'auteur anton_rh
Il y a beaucoup de réponses ici, mais je n'ai pas réussi, à trouver une version, qui effectue réel méthode de résolution de la commande, lorsque vous n'utilisez pas toutes les nouvelles fonctionnalités c++ (uniquement à l'aide de c++98).
Note: Cette version est testée et fonctionne avec vc++2013, g++ 5.2.0 et la onlline compilateur.
Alors je suis venu avec une version, qui utilise uniquement sizeof():
Démo en Live (avec extension de type de retour de la vérification et de la vc++2010 solution de contournement): http://cpp.sh/5b2vs
Pas de source, comme je suis venu avec moi-même.
Lors de l'exécution de la démonstration en Direct sur le compilateur g++, veuillez noter que la taille des matrices de 0 sont autorisés, ce qui signifie que le static_assert utilisés ne déclenche pas une erreur de compilation, même quand il échoue.
Couramment utilisée pour la solution de contournement consiste à remplacer la "typedef" dans la macro avec 'extern'.
Non, mais je suis déclarant en moi-même et il n'utilise pas rvalue (voir en haut de mon code). Ou vous pouvez simplement vous convaincre et essayez la démo en live dans c++98 mode. PS: static_assert n'est pas c++98, soit, mais il ya des solutions de rechange (démo)
oh pinaise! oubliée. 🙂
Votre statique affirme ne fonctionnent pas. Vous devez utiliser la taille de la matrice -1 au lieu de 0 (essayez de mettre
static_assert(false);
). J'ai été en utilisant ce dans le cadre de PROGRAMME de formation itinérante où je veux déterminer si la classe dérivée a une fonction particulière--qui s'avère ne pas travailler, mais votre affirme toujours transmis. J'ai perdu quelques cheveux.Je suis en supposant que vous êtes à l'aide de g++. Veuillez noter que gcc/g++ ont une extension qui permet de zéro-tableau de taille (gcc.gnu.org/onlinedocs/gcc/Zero-Length.html)
OriginalL'auteur user3296587
Comment sur cette solution?
toString
est surchargé, comme&U::toString
est ambigu.Je pense qu'un casting peut résoudre ce problème.
OriginalL'auteur user1095108
Voici ma version qui gère tous les possibles de la fonction membre surcharges arbitraire arité, y compris les fonctions membres de modèle, éventuellement avec des arguments par défaut. Il distingue 3 mutuellement exclusifs scénarios lors d'un appel de fonction membre pour certains type de classe, avec arg types: (1) valide, ou (2) ambigu, ou (3) non-viable. Exemple d'utilisation:
Maintenant, vous pouvez l'utiliser comme ceci:
Voici le code, écrit en c++11, cependant, vous pouvez facilement le porter (avec des modifications mineures) non c++11 qui a typeof extensions (par exemple gcc). Vous pouvez remplacer le HAS_MEM macro avec votre propre.
OriginalL'auteur Hui
Vous pouvez ignorer tout de la métaprogrammation en C++14, et il suffit d'écrire ceci à l'aide d'
fit::conditionnel
de la Ajustement bibliothèque:Vous pouvez également créer directement la fonction de la lambdas ainsi:
Toutefois, si vous utilisez un compilateur qui ne supporte pas les génériques lambdas, vous devrez écrire une fonction des objets:
fit
ou une bibliothèque autre que la norme?OriginalL'auteur Paul Fultz II
Voici un exemple du code de travail.
toStringFn<T>* = nullptr
permettra à la fonction qui prend supplémentaireint
argument qui a priorité sur la fonction qui prendlong
lorsqu'il est appelé avec0
.Vous pouvez utiliser le même principe pour les fonctions qui retourne
true
si la fonction est mise en œuvre.OriginalL'auteur tereshkd
J'ai eu un problème similaire:
Une classe de modèle qui peut être dérivée à partir de quelques classes de base, certains qui ont un certain nombre d'etats et d'autres qui ne le sont pas.
Je l'ai résolu de la même manière à la "typeof" (Nicola Bonelli) de réponse, mais avec decltype de sorte qu'il compile et s'exécute correctement sur MSVS:
OriginalL'auteur Yigal Eilam
OriginalL'auteur Abhishek