Может кто-нибудь объяснить следующее поведение (я использую 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;}
Чтобы сделать ситуацию еще более странной, если я изменю исходный файл на использование любого другого WeekDay, кроме 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;}
EDIT:
Кстати, я сделал отчет об ошибке, и это ответ от Microsoft: «Это ошибка, которая проявляется при попытке продвинуть параметр шаблона нетипичного типа. К сожалению, учитывая наши ограничения ресурсов для этого выпуска и что обойти доступно, мы не сможем это исправить в следующем выпуске Visual Studio. Обходной путь - изменить тип параметра шаблона на int. "
(я думаю, что «этот выпуск» относится к Visual Studio 2010)