SFINAE失败,带有枚举模板参数 [英] SFINAE failing with enum template parameter

查看:89
本文介绍了SFINAE失败,带有枚举模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以解释以下行为(我使用的是Visual Studio 2010)。

标头:

Can someone explain the following behaviour (I'm using 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,它可以正常编译:

But if I change the function template parameter from the enum type WeekDay to int, it compiles fine:

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;}

正常的功能模板专业化工作正常,没有任何意外:

Also the normal function template specialization works fine, no surprises there:

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

如果我改变了,这会使事情变得更奇怪源文件使用除MONDAY或TUESDAY之外的任何其他WeekDay,即 bool b = goToWork< THURSDAY>(); 错误更改为:

To make things even weirder, if I change the source file to use any other WeekDay than MONDAY or TUESDAY, i.e. bool b = goToWork<THURSDAY>(); the error changes to this:

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),看看是否发生了相同的事情,因为它似乎没有任何意义

Maybe someone could test this with a different compiler (other than Visual Studio 2010) to see if the same thing happens, because it doesn't seem to make any sense

编辑:我发现了一个新的有趣方面这种行为。也就是说,如果我将模板参数与 == != 的直接比较更改为与辅助结构模板,它可以正常工作:

I found a new "interesting" aspect of this behaviour. That is if I change the direct comparison of the template parameter with == and != operators into a comparison with a helper struct template, it works fine:

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。

By the way, I made a bug report and this is the answer from Microsoft: "This is a bug that manifests when attempting to promote the non-type template parameter. Unfortunately, given our resource constraints for this release and that a worked-around is available, we will not be able to fix this in the next release of Visual Studio. The work-around is to change the template parameter type to an int."

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

(I think "this release" refers to Visual Studio 2010)

推荐答案

在GCC中效果很好4.2.1。

Works fine in GCC 4.2.1.

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

Looks like either VC's template engine is missing comparison operators for enum types, or it sloppily converted the enum to int and then decided to be strict and disallow implicit conversion to int (apparently with an exception for 0 and 1).

这篇关于SFINAE失败,带有枚举模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆