3

有人可以解释以下行为(我使用的是 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 之外的任何其他工作日,即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;}

编辑:顺便说一句,我做了一个错误报告,这是微软的回答:“这是一个在尝试提升非类型模板参数时出现的错误。不幸的是,鉴于我们对此版本的资源限制并且有效-around 可用,我们将无法在 Visual Studio 的下一版本中修复此问题。解决方法是将模板参数类型更改为 int。

(我认为“此版本”是指 Visual Studio 2010)

4

1 回答 1

2

在 GCC 4.2.1 中运行良好。

看起来 VC 的模板引擎缺少枚举类型的比较运算符,或者它草率地将枚举转换为 int,然后决定严格并禁止隐式转换为 int(显然 0 和 1 除外)。

于 2010-05-06T13:20:02.583 回答