2010-05-04 6 views
3

Est-ce que quelqu'un peut expliquer le comportement suivant (j'utilise Visual Studio 2010).
tête:SFINAE échoue avec le paramètre de modèle enum

#pragma once 
#include <boost\utility\enable_if.hpp> 
using boost::enable_if_c; 

enum WeekDay {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}; 

template<WeekDay DAY> 
typename enable_if_c< DAY==SUNDAY, bool >::type goToWork() {return false;} 

template<WeekDay DAY> 
typename enable_if_c< DAY!=SUNDAY, bool >::type goToWork() {return true;} 

source:

bool b = goToWork<MONDAY>(); 

compilateur cela donne

error C2770: invalid explicit template argument(s) for 'enable_if_c<DAY!=6,bool>::type goToWork(void)' 

et

error C2770: invalid explicit template argument(s) for 'enable_if_c<DAY==6,bool>::type goToWork(void)' 

Mais si je change le modèle de fonction p arameter du type ENUM WeekDay à int, il compile bien:

template<int DAY> 
typename enable_if_c< DAY==SUNDAY, bool >::type goToWork() {return false;} 

template<int DAY> 
typename enable_if_c< DAY!=SUNDAY, bool >::type goToWork() {return true;} 

également la spécialisation normale de modèle de fonction fonctionne très bien, pas de surprise là:

template<WeekDay DAY> bool goToWork()   {return true;} 
template<>    bool goToWork<SUNDAY>() {return false;} 

Pour rendre les choses encore plus étrange, si je change la fichier source à utiliser toute autre WeekDay que lundi ou mardi, à savoir bool b = goToWork<THURSDAY>(); les changements d'erreur à ceci:

error C2440: 'specialization' : cannot convert from 'int' to 'const WeekDay' 
Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast) 

EDIT: peut-être que quelqu'un pourrait tester cela avec une dif compilateur indépendant (autre que Visual Studio 2010) pour voir si la même chose se produit, car cela ne semble pas avoir de sens

EDIT: J'ai trouvé un nouvel aspect "intéressant" de ce comportement. C'est si je change la comparaison directe du paramètre de modèle avec == et != opérateurs en comparaison avec un modèle de struct aide, il fonctionne très bien:

template<WeekDay DAY> 
struct Is 
{ 
    static const bool Sunday = false; 
}; 

template<> 
struct Is<SUNDAY> 
{ 
    static const bool Sunday = true; 
}; 

template<WeekDay DAY> 
typename enable_if_c< Is<DAY>::Sunday, bool >::type goToWork() {return false;} 

template<WeekDay DAY> 
typename enable_if_c< !Is<DAY>::Sunday, bool >::type goToWork() {return true;} 

EDIT: D'ailleurs, je fait un rapport de bogue et Voici la réponse de Microsoft: "C'est un bug qui se manifeste lors de la tentative de promotion du paramètre de template non-typ .. Malheureusement, étant donné nos contraintes de ressources pour cette version et qu'un work-around est disponible, nous ne pourrons pas résoudre ce problème. Dans la prochaine version de Visual Studio, la solution consiste à remplacer le type de paramètre de modèle par un int. "

(je pense "ce communiqué" fait référence à Visual Studio 2010)

Répondre

2

fonctionne très bien dans GCC 4.2.1. Il semble que le moteur de template de VC manque d'opérateurs de comparaison pour les types enum, ou il convertit négligemment l'enum en int, puis décide d'être strict et interdit la conversion implicite en int (apparemment avec une exception pour 0 et 1).

+0

Bon à savoir Je ne suis pas devenu fou. Je soupçonnais aussi que les opérateurs sont en quelque sorte absents, parce que non seulement les opérateurs de comparaison == et! = Mais aussi les logiques && et || faire des ravages. Désolé d'ignorer les utilisateurs mac. – zeroes00

Questions connexes