2010-11-16 24 views
0

J'ai trouvé un code C++ très intéressant sur stackoverflow et je suis très confus à ce sujet car comme l'auteur dit que cela devrait fonctionner et il échoue sur mon gcc 4.5.1 et 4.4 :( l'objectif est de vérifier si la classe contient ou non une méthode spécifiqueProblème lors de la vérification si la fonction existe en C++

le code est:.

#include <iostream> 

struct Hello 
{ 
    int helloworld() 
    { return 0; } 
}; 

struct Generic {}; 


// SFINAE test 
template <typename T> 
class has_helloworld 
{ 
    typedef char one; 
    typedef long two; 

    template <typename C> static one test(typeof(&C::helloworld)) ; 
    template <typename C> static two test(...); 


public: 
    enum { value = sizeof(test<T>(0)) == sizeof(char) }; 
}; 


int 
main(int argc, char *argv[]) 
{ 
    std::cout << has_helloworld<Hello>::value << std::endl; 
    std::cout << has_helloworld<Generic>::value << std::endl; 
    return 0; 
} 

J'ai erreur du compilateur:

ISO C++ forbids in-class initialization of non-const static member 'test'

Supplémentaires comme certains commentaire dit - je peux changer 'typeof (& C :: HelloWorld)' à 'char [sizeof (& C :: HelloWorld)]' mais ma sortie est

1 
1 

ce qui est faux, parce qu'une seule classe a la fonction helloworld

Existe-t-il une méthode pour le faire fonctionner? Addition Je serais très thankfull si quelqu'un pouvait expliquer ce qui fait exactement cette commande:

test(char[sizeof(&C::helloworld)]) ; 

Merci beaucoup :)

+3

Vous liez à ma réponse, mais ma réponse ne contient pas que 'typeof' chose. –

+1

Un, je suis surpris que cela vous donne une erreur à propos de 'test' étant un membre non-const - les deux instances de test ressemblent à des déclarations de fonction pour moi. Deux, ce n'est pas une réflexion. La réflexion implique la découverte des types, méthodes, membres, etc. Tout cela est fait statiquement à la compilation. –

Répondre

2

Votre problème est avec l'utilisation du zéro intégral et typeof. En utilisant MSVC10, decltype, et nullptr, c'est une modification triviale pour ce code d'imprimer les valeurs correctes.

template <typename T> 
class has_helloworld 
{ 
    typedef char one; 
    typedef long two; 

    template <typename C> static one test(decltype(&C::helloworld)) ; 
    template <typename C> static two test(...); 


public: 
    enum { value = std::is_same<decltype(test<T>(nullptr)), char>::value }; 
}; 


int main(int argc, char *argv[]) 
{ 
    std::cout << has_helloworld<Hello>::value << std::endl; 
    std::cout << has_helloworld<Generic>::value << std::endl; 
    std::cin.get(); 
    return 0; 
} 

Je ne suis pas un expert en typeof, mais quelque chose comme cela devrait être faisable:

struct no_type {}; 
// SFINAE test 
template <typename T> 
class has_helloworld 
{ 
    template <typename C> static typeof(&C::helloworld) test(C* i); 
    template <typename C> static no_type test(...); 


public: 
    enum { value = std::is_same<no_type, typeof(test<T>(0))>::value }; 
}; 
+0

merci beaucoup! :) –