En réponse à une autre question quelque part, j'ai écrit ce code.Erreurs utilisant decltype() et SFINAE
struct no_type{};
template<typename T> struct has_apply {
static decltype(T().apply<0u>(double())) func(T* ptr);
static no_type func(...);
static const bool result = !std::is_same<no_type, decltype(func(nullptr))>::value;
};
class A {
public:
template< unsigned n >
void apply(const double&);
};
class B {
};
int main()
{
std::cout << std::boolalpha << has_apply<A>::result << '\n';
std::cout << std::boolalpha << has_apply<B>::result << '\n';
std::cin.get();
return(0);
}
Maintenant, il me semble à ce résultat devrait être vrai si T offre une fonction membre non statique « appliquer » qui accepte un double rvalue et un paramètre de modèle littéral, et false sinon. Toutefois, l'exemple donné ne parvient pas à compiler pour la classe B lors de la compilation has_apply<B>
. Le fait que la substitution de T ait échoué dans l'instruction decltype ne devrait-il pas signifier qu'il appelle simplement l'autre func? N'est-ce pas le genre de SFINAE?
résolus à la mode inutile le plus ridicule jamais:
struct no_type{};
template<typename T> struct has_apply {
template<typename U> static decltype(U().apply<0u>(double())) func(U*);
template<typename U> static no_type func(...);
static const bool result = !std::is_same<no_type, decltype(func<T>(nullptr))>::value;
};
class A {
public:
template< unsigned n >
void apply(const double&);
};
class B {
};
int main()
{
std::cout << std::boolalpha << has_apply<A>::result << '\n';
std::cout << std::boolalpha << has_apply<B>::result << '\n';
std::cin.get();
return(0);
}
Vous devez également utiliser declval() au lieu de T() dans le cas où T n'a pas de constructeur par défaut. VS2010 ne l'a pas mais il peut être fait: http://stackoverflow.com/questions/2638843/should-i-use-c0x-features-now –
@Noah Roberts: C'est vrai! Cela fait partie des raisons pour lesquelles j'ai dit 'au moins' ci-dessus;) – usta
@usta: Je ne comprends toujours pas. T n'est pas un type dépendant, c'est le type de modèle. Si vous créez une variable membre de type T, vous ne dites pas 'typename T t;', ce que vous faites pour les types dépendants. – Puppy