Потоковая передача в исключительный класс - PullRequest
4 голосов
/ 15 марта 2012

У меня есть базовый класс Exception, который определяет функцию потока:

class Exception
{
public:
    template <typename TData, typename TException>
    TException& stream(const TData& data)
    {
        stream_ << data;
        return *reinterpret_cast<TException*>(this);
    }
};

У меня есть свободный оператор перегрузки функций <<: </p>

template <typename TData>
Exception& operator<<(Exception& ex, const TData& data) {
    return ex.stream<TData, Exception>(data);
}

У меня также есть оператор перегрузки исключений с перегрузкой<<: </p>

template <typename TData>
CoffeeException& operator<<(CoffeeException& ex, const TData& data) {
    return ex.stream<TData, CoffeeException>(data);
}

Я использую это так:

else {
    throw CoffeeException() << "Exception text";
}

Когда я пытаюсь использовать класс, компилятор не видит функцию, он просто предлагает стандартные операторы потокадоступно, но не замечает мои бесплатные функции Exception или CoffeeException.Эта реализация выглядит правильно?

Ответы [ 2 ]

8 голосов
/ 15 марта 2012

Это похоже на обычную проблему попытки связать временную ссылку с неконстантной ссылкой.CoffeeException() << "Exception text" не может привязаться к вашему operator<<, потому что CoffeeException() является временным.Просто сделайте ваш operator<< участником:

class CoffeeException : public Exception
{
    //  ...
public:
    template <typename TData>
    CoffeeException& operator<<( TData const& data )
    {
        stream( data );
        return *this;
    }
};

Пока я в этом: вам определенно не нужен reinterpret_cast в конце Exception::stream.Использование результатов этого броска - неопределенное поведение.Обычно это работает в случаях одиночного наследования, но терпит неудачу, когда задействовано множественное наследование (но даже это не гарантируется).Самое простое решение - это то, что я сделал выше (и заставить Exception::stream return void);в качестве альтернативы используйте static_cast здесь (что должно быть законно, если наследование определено в момент создания экземпляра).

0 голосов
/ 15 марта 2012
CoffeeException& operator<<(const CoffeeException& ex, const TData& data);

Эта ссылка должна быть константной, поскольку вы пытаетесь передать безымянный объект.Вы также можете создать временный объект, чтобы избежать использования константной ссылки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...