有人可以解释以下行为(我正在使用Visual Studio 2010)。
header :

#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参数的直接比较更改为与helper struct模板的比较,则可以正常工作:
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;}

编辑:
顺便说一句,我做了一个错误报告,这是Microsoft的回答:“这是一个错误,它在尝试提升非类型模板参数时表现出来。不幸的是,考虑到我们对该版本的资源限制和一种解决方法,可用,我们将无法在下一版本的Visual Studio中修复此问题。解决方法是将模板参数类型更改为int。”

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

最佳答案

在GCC 4.2.1中可以正常工作。

看起来是VC的模板引擎缺少枚举类型的比较运算符,还是将其枚举草率地转换为int,然后决定严格,不允许隐式转换为int(显然0和1除外)。

关于c++ - SFINAE失败,带有枚举模板参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2763836/

10-11 22:54
查看更多