MSVC 10 and MSVC 9 are both generating a level 4 warning message when compiling my exception framework, although the behavior of the program seems correct. The exception framework is rather large & complex, but I have managed to boil it down to its essence. This is a complete program you can compile & 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 line 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 append source file information to every thrown exception. I use a macro that evaluates to throw ex::make_traced_error(__FILE_, __LINE__, ex);
, but that was not necessary to replicate the compiler warning.
make_traced_error
instantiates a template exception class, the template parameter for which is the exception being thrown, in this case generic_error
. Obviously if I simply throw a plain generic_error
the compiler is happy, but this is not what I want to do.
What is the cause and effect of this warning? Is the compiler wrong, or is my code? I should note a couple things here.
First, when I execute this code it does what I expect it to do. The generic_error
catch block is called rather than the general exception
block, and the output of the program is:
gex = traced error on line 51 :
Second, when I compile this code with the Comeau online compiler it compiles without error or warning, suggesting to me that my code is Standards-compliant and legal C++. Correct assumption?
'generic error in thread #234'
Finally, I have seen the MS knowledge base article about this warning. But MS's explanation was fully unsatisfactory (it did not explain the cause of the warning), and their resolution is unacceptable -- they say that I should just throw a straight generic_error
.