Вывод аргумента шаблона класса с типом enum?
Редактировать: Я считаю, что этот вопрос был ошибочно помечен как дубликат, особенно с учетом "дубликатов". Пожалуйста, смотрите ниже.
Сегодня я попытался (впервые) использовать вывод аргументов шаблонной функции.
Моя цель - внедрить простую систему статусов. Следующий код (надеюсь) показывает важные части (я не тестировал его, это просто для иллюстрации проблемы):
class StatusBase
{
int m_globalStatus;
protected:
// The module type should be found by template argument deduction
template <class Module>
void SetStatus(enum Module::Status localStatus)
{
// Do something with Module
m_globalStatus = SomeOtherModule<Module>::ToGlobal(localStatus);
}
};
А вот как некоторые классы могут использовать класс StatusBase.
class DerivedA : public StatusBase
{
public:
enum Status {
OK,
WARNING,
ERROR
};
DerivedA ()
{
SetStatus(OK); // doesn't work
SetStatus(DerivedA::OK); // doesn't work
SetStatus<DerivedA>(OK); // this works
}
};
Другой класс будет иметь другое перечисление:
class DerivedB : public StatusBase
{
public:
enum Status {
OTHER_OK,
OTHER_WARNING
};
...
};
Интересная часть - это вызов SetStatus. Для первых двух строк, которые не работают, компилятор жалуется, что
couldn't deduce template parameter `Module'
Когда я явно указываю модуль (как в третьей строке), программа компилируется.
Мои вопросы:
Разве компилятор не должен выводить тип модуля в первых двух строках?! Почему это не работает, как ожидалось?
Есть ли способ, которым я могу просто вызвать SetStatus(ОК); без явного указания типа модуля? Будет ли проще решить эту проблему с C++11?
Спасибо!
Используется компилятор g++ 4.9.2
Редактировать: я считаю, что "не выводимый контекст" из так называемых "дубликатов" answer1 и answer2 здесь не применим.
Классический пример не выводимого контекста из других случаев таков:
template <typename T>
void g(typename Foo<T>::type);
Мой случай другой:
template <typename T>
void SetStatus(enum T::Status localStatus)
В других случаях существует вероятность неоднозначности, особенно потому, что тип Foo
:: type не имеет ничего общего с самим T. Это было четко указано в ответе2. Я не вижу никакой возможности двусмысленности в моем случае. Если я не прав, пожалуйста, докажите это, приведя пример того, как мой код может привести к неоднозначности.
Как уже указывалось в моем комментарии, я считаю, что по логике (а не по правильному использованию семантики вывода аргументов шаблона, что я, очевидно, сделал неправильно), компилятор может определить тип.
Пожалуйста, удалите дубликат флага и ответьте на мои оригинальные вопросы.