有人可以解释以下行为(我正在使用Visual Studio 2010) 标题:
#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;}
来源:
bool b = goToWork<MONDAY>();
编译器给出了
error C2770: invalid explicit template argument(s) for 'enable_if_c<DAY!=6,bool>::type goToWork(void)'
和
error C2770: invalid explicit template argument(s) for 'enable_if_c<DAY==6,bool>::type goToWork(void)'
但是如果我将函数模板参数从枚举类型WeekDay更改为int,它编译得很好:
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;}
正常的功能模板专业化也很好,没有惊喜:
template<WeekDay DAY> bool goToWork() {return true;}
template<> bool goToWork<SUNDAY>() {return false;}
为了让事情变得更奇怪,如果我将源文件更改为使用除MONDAY或TUESDAY之外的任何其他WeekDay,即bool b = goToWork<THURSDAY>();
,则错误更改为:
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)
编辑:也许有人可以用不同的编译器(除了Visual Studio 2010)测试这个,看看是否发生了同样的事情,因为它似乎没有任何意义
编辑:我发现了这种行为的新“有趣”方面。也就是说,如果我将模板参数与==
和!=
运算符的直接比较更改为与辅助结构模板的比较,则可以正常工作:
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;}
编辑: 顺便说一句,我做了一个错误报告,这是微软的答案:“这是一个在尝试推广非类型模板参数时出现的错误。不幸的是,考虑到我们对此版本的资源限制以及解决方法如果可用,我们将无法在Visual Studio的下一个版本中修复此问题。解决方法是将模板参数类型更改为int。“
(我认为“此版本”指的是Visual Studio 2010)
答案 0 :(得分:2)
在GCC 4.2.1中正常工作。
看起来VC的模板引擎缺少enum类型的比较运算符,或者它将enum转换为int然后决定是严格的并禁止隐式转换为int(显然有0和1的异常)。