MSVC 10 und MSVC 9 erzeugen beide eine Level 4-Warnmeldung beim Kompilieren meines Ausnahmeframeworks, obwohl das Verhalten des Programms scheint richtig zu sein. Das Ausnahme-Framework ist ziemlich groß, aber ich habe es geschafft, es auf seine Essenz herunterzukochen. Dies ist ein komplettes Programm, das Sie & Lauf in VS10 kompilierenwarning C4673: werfend 'ex :: traced_error <EX>' die folgenden Typen werden in der Catch-Site nicht berücksichtigt
#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;
}
}
Wenn die Zeile Kompilieren throw ex::make_traced_error(__LINE__, ex::generic_error(234));
der Compiler gibt:
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> ]
Eines der Ziele dieser Ausnahme-Bibliothek ist Quelldatei Informationen anhängen jede geworfene Ausnahme. Ich verwende ein Makro, das throw ex::make_traced_error(__FILE_, __LINE__, ex);
auswertet, aber das war nicht erforderlich, um die Compilerwarnung zu replizieren.
make_traced_error
instanziiert eine Vorlagenausnahmeklasse, deren Vorlagenparameter die Ausnahme ist, die ausgelöst wird, in diesem Fall generic_error
. Offensichtlich, wenn ich einfach eine einfache generic_error
werfe den Compiler ist glücklich, aber das ist nicht das, was ich tun möchte.
Was ist die Ursache und Wirkung dieser Warnung? Ist der Compiler falsch oder mein Code? Ich sollte hier ein paar Dinge notieren.
Erstens, wenn ich diesen Code ausführen, tut es, was ich erwarte es zu tun. Der generic_error
catch-Block wird aufgerufen, anstelle der allgemeinen exception
Block, und die Ausgabe des Programms ist:
gex = verfolgt Fehler in Zeile 51:
Zweitens, wenn ich diesen Code mit dem kompilieren Comeau online compiler es kompiliert ohne Fehler oder Warnung und schlägt mir vor, dass mein Code Standards-compliant und legal C++ ist. Richtige Annahme?
'allgemeine Fehler in thread # 234'
Schließlich habe ich die MS knowledge base article über diese Warnung gesehen. Aber die Erklärung von MS war völlig unbefriedigend (sie erklärte nicht die Ursache der Warnung), und ihre Lösung ist inakzeptabel - sie sagen, dass ich einfach eine direkte generic_error
werfen sollte.
Ich würde vermuten, dass dies eine falsche Warnung ist. Beachten Sie, dass "die folgenden Typen" angegeben sind, aber keine Typen aufgeführt sind. –
@ James: Ich glaube, die "folgenden Typen" bezieht sich auf die nächste Zeile, in der es 'generic_error' erwähnt. MS-Compiler-Fehler sind oft multi-line –
Der 'mit [...]' Teil gibt an, dass, wenn es sagt "ex :: traceed_error" in der ersten Zeile des Fehlers, die Vorlage Argumente der instanziierten Vorlage sind was im '...' Teil aufgeführt ist. Wenn Sie 'traced_error' so ändern, dass private Vererbung verwendet wird, erhalten Sie eine weitere Zeile, die' ex :: generic_error' als einen Typ aufführt, der bei einer Auffangstelle nicht berücksichtigt wird. –