Warning C4673: throw 'ex :: traced_error <EX>' the following types will not be considered on the catch site
MSVC 10 and MSVC 9 generate a level 4 warning message when compiling my exception framework, although the behavior of the program seems to be correct. The structure of exceptions is quite large and complex, but I managed to bring it to its essence. This is a complete program that you can compile and run in 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; } } When compiling the string throw ex::make_traced_error(__LINE__, ex::generic_error(234)); the compiler emits:
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> ] One of the goals of this exception library is to add source file information to each exception that is thrown. I use a macro that evaluates to throw ex::make_traced_error(__FILE_, __LINE__, ex); , but this is not necessary for compiler warning replication.
make_traced_error creates an instance of the template exception class, the template parameter for which the exception is thrown, in this case generic_error . Obviously, if I just throw a simple generic_error , the compiler will be happy, but thatβs not what I want to do.
What is the cause and effect of this warning? Is the compiler or my code wrong? Here I have to mention a couple of things.
First, when I execute this code, it does what I expect from it. The catch generic_error block generic_error called, not the general exception block, but the program output:
gex = traced error on line 51:
Secondly, when I compile this code using the Comau online compiler , it compiles without errors or warnings, suggesting that my code be standard, compatible and legal C ++. The correct assumption?
'general error in stream # 234'
Finally, I saw an MS Knowledge Base article about this warning. But the explanation of MS was completely unsatisfactory (this did not explain the reason for the warning), and their resolution is unacceptable - they say that I should just throw a direct generic_error .
The problem is indirectly related to multiple virtual inheritance from std::exception . The compiler is confused because of this, but forgets to tell you why.: - /
James McNellis is right: the promises compiler to specify the type, but it is not. Try without 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; } } When compiled with level 4 warnings, this says nothing more than:
warning C4673: throwing "Derv" the following types will not be considered on the catch site
I see the meaning of the warnings. But, obviously, level 4 in this case is buggy. Since everything works as expected, you can simply disable the compiler:
#pragma warning(disable: 4673) I think you could report this case as a bug in Microsoft. The compiler should indicate the type and problem.