Comment gérer noexcept dans Visual Studio

J’essaie de créer une exception personnalisée dérivant de std::exception et what() remplace what() . Au début, je l’ai écrit comme ceci:

 class UserException : public std::exception { private: const std::ssortingng message; public: UserException(const std::ssortingng &message) : message(message) {} virtual const char* what() const override { return message.c_str(); } }; 

Cela fonctionne bien dans VS2012, mais il ne comstack pas dans GCC 4.8 avec -std=c++11 :

erreur: spécificateur de jet plus lâche pour ‘virtuel const char * UserException :: what () const’

Donc j’ajoute noexcept :

 virtual const char* what() const noexcept override 

Cela fonctionne bien dans GCC, mais il ne comstack pas dans Visual Studio (car VS 2012 ne supporte pas noexcept ):

erreur C3646: ‘noexcept’: spécificateur de remplacement inconnu

Quelle est la manière recommandée de gérer cela? Je veux que le même code comstack avec les deux compilateurs et que j’utilise les fonctionnalités de C ++ 11, donc je ne peux pas comstackr avec différents -std .

Utiliser une macro

 #ifndef _MSC_VER #define NOEXCEPT noexcept #else #define NOEXCEPT #endif 

Et ensuite définir la fonction comme

 virtual const char* what() const NOEXCEPT override 

Vous pouvez également modifier cela pour autoriser noexcept sur les versions ultérieures de VS en vérifiant la valeur de _MSC_VER ; pour VS2012, la valeur est 1600.

“noexcept” est uniquement pris en charge depuis Visual Studio 2015 (comme indiqué ici: https://msdn.microsoft.com/en-us/library/wfa0edys.aspx ). J’ai utilisé le code suivant avec Visual Studio 2013 (dérivé des exemples ci-dessus):

 #if !defined(HAS_NOEXCEPT) #if defined(__clang__) #if __has_feature(cxx_noexcept) #define HAS_NOEXCEPT #endif #else #if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \ defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 #define HAS_NOEXCEPT #endif #endif #ifdef HAS_NOEXCEPT #define NOEXCEPT noexcept #else #define NOEXCEPT #endif 

Ce contrôle fonctionne pour voir si noexcept est pris en charge:

 // Is noexcept supported? #if defined(__clang__) && __has_feature(cxx_noexcept) || \ defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \ defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180021114 # define NOEXCEPT noexcept #else # define NOEXCEPT #endif 

Ce qui précède fonctionne avec Clang, GCC et MSVC.

utilisez BOOST_NOEXCEPT dans

La bibliothèque de configuration boost a été conçue pour des problèmes de compatibilité comme celui-ci. Selon le doc :

Si BOOST_NO_CXX11_NOEXCEPT est défini (c’est-à-dire des compilateurs compatibles C ++ 03), ces macros sont définies comme suit:

  #define BOOST_NOEXCEPT #define BOOST_NOEXCEPT_OR_NOTHROW throw() #define BOOST_NOEXCEPT_IF(Predicate) #define BOOST_NOEXCEPT_EXPR(Expression) false 

Si BOOST_NO_CXX11_NOEXCEPT n’est pas défini (c’est-à-dire des compilateurs compatibles C ++ 11), ils sont définis comme suit:

  #define BOOST_NOEXCEPT noexcept #define BOOST_NOEXCEPT_OR_NOTHROW noexcept #define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate)) #define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression)) 

Beaucoup des autres réponses ici ont une implémentation similaire, mais cette bibliothèque est plus propre, mieux testée et fera ce qu’il faut quand votre compilateur est mis à niveau. Je recommande d’examiner la bibliothèque de configuration de boost en général pour d’autres fonctionnalités, en particulier en cette période de stream de langage et de niveaux de support variables parmi les compilateurs.

Le noexcept est l’un des “manques” les plus faciles à traiter avec _NOEXCEPT : utilisez simplement la macro _NOEXCEPT qui sous MSVC2013 est définie dans yvals.h.

Ajoutez les lignes suivantes dans votre code dans Visual Studio:

 #ifdef _NOEXCEPT #define noexcept _NOEXCEPT #endif 

Ce que j’ai récemment utilisé est le suivant:

 #ifdef _MSC_VER #define NOEXCEPT _NOEXCEPT #else #define NOEXCEPT noexcept #endif 

puis utilisez simplement NOEXCEPT partout.

Il semble que l’ancien throw() (déconseillé en C ++ 11) fonctionne dans les deux compilateurs. J’ai donc changé le code pour:

 virtual const char* what() const throw() override 

L’autre façon de contourner le problème est de créer un fichier d’en-tête et de l’inclure si nécessaire dans votre code source qui devrait être compilé par gcc, vc ou clang.

no_except_work_around.h

 #ifndef no_except_work_around_H #define no_except_work_around_H #if (_MSC_VER <= 1800) #include  #define noexcept #endif #endif //no_except_work_around_H 

================================================== ===

PS> ne couvre pas le cas noexcept (false) mais fonctionne bien pour VC2010,2012,2013, gcc 4.9

#IF s peut fonctionner, même si c’est un peu piraté.

Vous pourriez juste faire ceci:

 #if __GNUG__ virtual const char* what() const noexcept override #else virtual const char* what() const override #endif //method body