Использование шаблона для возвращаемого значения. как обращаться с недействительным возвратом?

У меня есть структура для хранения функции обратного вызова:

template<class T>
struct CommandGlobal : CommandBase
{
    typedef boost::function<T ()> Command;
    Command comm;

    virtual T Execute() const
    {
        if(comm)
            return comm();
        return NULL;
    }
};

Кажется, что он должен работать нормально, кроме случаев, когда T недействителен, потому что функция Execute хочет вернуть значение.

Какое наилучшее решение этой проблемы?

Спасибо!

Ответ 1

Этот ответ основан на этом забавном факте: в функции, возвращающей void, вы можете вернуть любое выражение, тип которого недействителен.

Итак, простое решение:

virtual T Execute() const
{
    if (comm) // boolean logic change, typo in OP?
        return comm();
    else
        return static_cast<T>(NULL);
}

Когда T = void, последний оператор возврата эквивалентен return;.


Однако, я чувствую, что это плохой дизайн. Является ли NULL значимым для каждого T? Я так не думаю. Я бы выбрал исключение:

virtual T Execute() const
{
    if (comm)
        return comm();
    else
        throw std::runtime_error("No function!")
}

Однако это делается автоматически с помощью Boost, поэтому ваш код становится намного чище:

virtual T Execute() const
{
    return comm();
}

Затем вы можете добавить дополнительные функции, например:

bool empty(void) const
{
    return !comm; // or return comm.empty() if you're the explicit type
}

Таким образом, пользователь может проверить, можно ли его вызвать до вызова. Конечно, на данный момент, если у вашего класса нет дополнительной функциональности, которую вы оставили вне для вопроса, я не вижу причин не просто использовать boost::function в первую очередь.

Ответ 2

Если это просто оператор return, это должно сделать трюк:

virtual T Execute() const
{
    if(comm)
        return comm();
    return T();
}

Если это еще не так, специализируйте шаблон для void.