Вывод аргумента шаблона класса с типом 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'

Когда я явно указываю модуль (как в третьей строке), программа компилируется.

Мои вопросы:

  1. Разве компилятор не должен выводить тип модуля в первых двух строках?! Почему это не работает, как ожидалось?

  2. Есть ли способ, которым я могу просто вызвать 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)
  1. В других случаях существует вероятность неоднозначности, особенно потому, что тип Foo :: type не имеет ничего общего с самим T. Это было четко указано в ответе2.

  2. Я не вижу никакой возможности двусмысленности в моем случае. Если я не прав, пожалуйста, докажите это, приведя пример того, как мой код может привести к неоднозначности.

  3. Как уже указывалось в моем комментарии, я считаю, что по логике (а не по правильному использованию семантики вывода аргументов шаблона, что я, очевидно, сделал неправильно), компилятор может определить тип.

Пожалуйста, удалите дубликат флага и ответьте на мои оригинальные вопросы.

0 ответов

Другие вопросы по тегам