“appel à l'supprimé constructeur de” erreur de compilateur pour le std::runtime_error sous-classe
J'ai dérivé d'une classe d'exception de std::runtime_error
afin d'ajouter le support pour la diffusion des exceptions. Je suis une étrange erreur de compilation sortie avec clang que je ne suis pas sûr de la façon de résoudre?
clang++ -std=c++11 -stdlib=libc++ -g -Wall -I../ -I/usr/local/include Main.cpp -c
Main.cpp:43:19: error: call to deleted constructor of 'EarthException'
throw EarthException(__FILE__, __LINE__)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../EarthException.hpp:9:12: note: function has been explicitly marked deleted here
struct EarthException : public Exception<EarthException>
template <typename TDerived>
class Exception : public std::runtime_error
{
public:
Exception() : std::runtime_error("") {}
Exception(const std::string& file, const unsigned line)
: std::runtime_error("")
{
stream_ << (file.empty() ? "UNNAMED_FILE" : file) << "[" << line << "]: ";
}
virtual ~Exception() {}
template <typename T>
TDerived& operator<<(const T& t)
{
stream_ << t;
return static_cast<TDerived&>(*this);
}
virtual const char* what() const throw()
{
return stream_.str().c_str();
}
private:
std::stringstream stream_;
};
struct EarthException : public Exception<EarthException>
{
EarthException() {}
EarthException(const std::string& file, const unsigned line)
: Exception<EarthException>(file, line) {}
virtual ~EarthException() {}
};
}
Mise à JOUR:
J'ai maintenant ajouté des appels explicites à std::runtime_error("")
comme il a été souligné le constructeur par défaut sur cela a été marquée comme =delete
cependant l'erreur reste.
OriginalL'auteur Graeme | 2012-08-25
Vous devez vous connecter pour publier un commentaire.
En raison de l'utilisateur déclaré destructeurs dans
Exception
etEarthException
, implicite génération du constructeur de déplacement et de déplacer des opérateurs d'affectation de ces classes est désactivé. Et à cause de l'évolution des données membrestd::stringstream
, implicite copier les membres sont supprimés.Cependant tout cela est une source de distraction.
Votre
what
membre est condamné:Cela crée une rvalue
std::string
, puis renvoie un pointeur sur que temporaire. Le temporaire détruit avant que le client ne peut jamais lu le pointeur dans que temporaire.Ce que vous devez faire est de passer un
std::string
jusqu'à lastd::runtime_error
de la classe de base. Ensuite, vous n'avez pas besoin de tenir unestringstream
, ou tout autre membre de données. La seule partie délicate est l'initialisation de lastd::runtime_error
de la classe de base avec le bonstring
:Maintenant, vous aurez implicite copier les membres et les choses vont juste travailler.
Si vous voulez l'exception déplacer seule, il n'y a pas de nécessité d'introduire
unique_ptr
.stringstream
est également déplacer seule. Vous pouvez la considérer comme sa propreunique_ptr
. Mais je pense que vous aurez également besoin de stocker unestd::string
(en plus que dansruntime_error
. Depuiswhat
doit retourner uneconst char*
, le pointeur doit pointer vers quelque chose de permanent (comme un membre de données). Vous ne pouvez pas l'avoir point dans une mesure temporaire. En un mot, la conception de lawhat
d'abord, et ensuite faire tout ce qui est nécessaire à l'appui de cettewhat
.Oui, merci, je comprends parfaitement le problème avec le retour d'un const char* à un emploi temporaire, c'était un oubli de ma part! Je ne suis pas encore tout à fait clair pourquoi ce n'est pas la compilation si std::stringstream se déplacer seul, je suppose que ma classe n'est pas seulement se déplacer dans ce cas, je suppose que je besoin de fournir un constructeur de déplacement et l'opérateur=?
Oui, vous devez fournir votre propre déplacer des membres si vous le souhaitez. L'utilisateur déclaré destructeurs inhiber le compilateur à partir de la fourniture de ces. Et je ne crois pas que vous serez en mesure explicitement par défaut c'est le moment, mais vous pouvez peut-être dans l'avenir. Il y a un problème de langue en cours de discussion en commission sur cette partie: open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1402
Vous avez raison, même en supprimant les destructeurs de la définition de la classe de l'erreur du compilateur reste. Merci pour l'aide.
OriginalL'auteur Howard Hinnant
Ce constructeur n'a pas fait appel à son constructeur de base, de sorte que le compilateur génère un appel au constructeur par défaut,
std::runtime_error::runtime_error()
. Maisstd::runtime_error
ne possède pas de constructeur par défaut, qui est ce que le message d'erreur est vous dire. Pour résoudre ce problème, lisez à propos destd::runtime_error
et appeler l'un de ses constructeurs.EDIT: bon, voici le réel problème (non pas que ce que j'ai l'adresse ci-dessus n'est pas un problème, aussi): le modèle
Exception
a un membre de données de typestd::stringstream
; les cours d'eau ne peuvent pas être copiés, de sorte que le compilateur ne peut pas générer un constructeur de copie à utiliser pour le lancer.std::runtime_error
est marqué avec= delete
, qui indique au compilateur de ne pas générer, même si il ne le ferait autrement. Ressemble à la message d'erreur s'est un peu embrouillé...J'ai maintenant ajouté des appels explicites à std::runtime_error (""), mais encore voir le message d'erreur 🙁
Parfait, génial merci!
OriginalL'auteur Pete Becker