предупреждение C4673: сгенерировав 'ex :: traced_error <EX>', следующие типы не будут рассматриваться на сайте улова - PullRequest
5 голосов
/ 27 августа 2010

MSVC 10 и MSVC 9 генерируют предупреждающее сообщение уровня 4 при компиляции моей структуры исключений, хотя поведение программы кажется правильным.Структура исключений довольно большая и сложная, но мне удалось свести ее к сути.Это полная программа, которую вы можете скомпилировать и запустить в VS10

#include <cstdlib>
#include <stdexcept>
#include <string>
#include <iostream>
#include <sstream>
using namespace std;

    namespace ex
    {
        class generic_error : virtual public std::exception
        {
        public:
            generic_error(int thread_id) : thread_id_(thread_id) {}
            const char* what() const throw()
            {
                static std::string msg;
                stringstream ss;
                ss << "generic error in thread #" << thread_id_;
                msg = ss.str();
                return msg.c_str();
            }
            int thread_id_;
        };

        template<class EX>
        class traced_error : virtual public std::exception, virtual public EX
        {
        public:
            traced_error(int line, const EX& ex):   EX(ex), line_(line) { }
            const char* what() const throw()
            {
                static std::string msg;
                stringstream ss;
                ss << "traced error on line " << line_ << " : '" << EX::what() << "'";
                msg = ss.str();
                return msg.c_str();
            }
            int line_;
        };

        template<class EX> traced_error<EX> make_traced_error(int line, const EX& ex)
        {
            return traced_error<EX>(line, ex);
        }
}

    int main()
    {
        try
        {
            throw ex::make_traced_error(__LINE__, ex::generic_error(234));
        }
        catch( const ex::generic_error& gex )
        {
            cout << "gex = " << gex.what();
            return 2;
        }
        catch( const exception& ex )
        {
            cout << ex.what();
            return 1;
        }
    }

При компиляции строки throw ex::make_traced_error(__LINE__, ex::generic_error(234)); компилятор выдает:

1>hacks_vs10.cpp(51): warning C4673: throwing 'ex::traced_error<EX>' the following types will not be considered at the catch site
1>          with
1>          [
1>              EX=ex::generic_error
1>          ]

Одной из целей этой библиотеки исключений являетсядобавить информацию исходного файла к каждому выброшенному исключению.Я использую макрос, который оценивается как throw ex::make_traced_error(__FILE_, __LINE__, ex);, но это не было необходимо для репликации предупреждения компилятора.

make_traced_error создает экземпляр класса шаблонного исключения, параметр шаблона для которого является генерируемым исключением, в данном случае generic_error.Очевидно, что если я просто выброшу простую generic_error, то компилятор будет счастлив, но я не хочу этого делать.

В чем причина и следствие этого предупреждения?Компилятор не прав или мой код?Я должен отметить пару вещей здесь.

Во-первых, когда я выполняю этот код, он делает то, что я ожидаю.Блок захвата generic_error вызывается вместо общего блока exception, и вывод программы:

gex = отслеженная ошибка в строке 51:

Во-вторых, когда я компилирую этот код с помощью онлайн-компилятора Comeau , он компилируется без ошибок или предупреждений, предлагая мне, что мой код соответствует стандартам и легален для C ++.Правильное предположение?

'общая ошибка в потоке # 234'

Наконец, я видел статью базы знаний MS об этом предупреждении.Но объяснение М.С. было полностью неудовлетворительным (оно не объясняло причину предупреждения), и их решение недопустимо - они говорят, что я должен просто бросить стрит generic_error.

1 Ответ

6 голосов
/ 30 августа 2010

Проблема косвенно связана с множественным виртуальным наследованием от std::exception.Из-за этого компилятор запутывается, но забывает сказать, почему.: - /

Джеймс МакНеллис прав: компилятор обещает упомянуть тип, но это не так.Попробуйте без template:

#include <stdexcept>

class Base: virtual public std::exception {};
class Derv: public Base, virtual public std::exception {};

int main()
{
  try {
    throw Derv();
  } catch (const Base &) {
    return 2;
  } catch (...) {
    return 1;
  }
}

Когда скомпилировано с предупреждениями уровня 4, это говорит только о:

предупреждении C4673: бросание 'Derv' следующих типов не будетбыть рассмотрены на месте улова

Я вижу значение предупреждений.Но, видимо, уровень 4 глючит в этом случае.Поскольку все работает, как и ожидалось, вы можете просто отключить компилятор:

#pragma warning(disable: 4673)

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

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