web-dev-qa-db-fra.com

Comment gérer noexcept dans Visual Studio

J'essaie de créer une exception personnalisée qui dérive de std::exception et remplace what(). Au début, je l’écrivais comme ceci:

class UserException : public std::exception
{
private:
    const std::string message;
public:
    UserException(const std::string &message)
        : message(message)
    {}

    virtual const char* what() const override
    {
        return message.c_str();
    }
};

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

error: spécificateur de projection plus lâche pour 'virtual const char * UserException :: what () const'

J'ajoute donc noexcept:

virtual const char* what() const noexcept override

Cela fonctionne bien dans GCC, mais il ne compile pas dans Visual Studio (car VS 2012 ne prend pas en charge noexcept):

erreur C3646: 'noexcept': spécificateur de substitution inconnu

Quelle est la façon recommandée de gérer cela? Je veux que le même code soit compilé avec les deux compilateurs et que j'utilise les fonctionnalités de C++ 11. Je ne peux donc pas compiler avec un -std différent.

43
svick

Utilisez 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.

43
Praetorian

"noexcept" n'est pris en charge que 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
15
ivan.ukr

Cette vérification permet de 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.

12
marton78

utiliser BOOST_NOEXCEPT dans <boost/config.hpp>

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

Si BOOST_NO_CXX11_NOEXCEPT est défini (c'est-à-dire des compilateurs conformes à 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 conformes à 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 le bon choix lorsque votre compilateur sera mis à niveau. Je recommande de regarder la bibliothèque boost config en général pour d'autres fonctionnalités, en particulier en cette période de flux de langue et de niveaux de support variables parmi les compilateurs.

9
evan

Le noexcept est l'un des "manques" les plus faciles à résoudre de MSVC: utilisez simplement la macro _NOEXCEPT qui, sous MSVC2013, est définie dans yvals.h.

3
patlecat

Ajoutez les lignes suivantes dans votre code dans Visual Studio:

#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif
3

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

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

et ensuite, utilisez simplement NOEXCEPT partout.

2
ivan.ukr

Il semble que l'ancien throw() (obsolète en C++ 11) fonctionne dans les deux compilateurs. J'ai donc changé le code en:

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

L'autre solution consiste à créer un fichier d'en-tête et à 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 <xkeycheck.h>
#define noexcept
#endif 

#endif //no_except_work_around_H

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

P.S> ne couvre pas le cas Noexcept (false) Mais fonctionne bien pour VC2010,2012,2013, gcc 4.9

1
Alexei Valyaev

#IFs peut fonctionner, même si c'est un peu hacky.

Vous pouvez simplement faire ceci:

#if __GNUG__
virtual const char* what() const noexcept override
#else
virtual const char* what() const override
#endif
//method body
0
It'sNotALie.

ajoutez le chemin ci-dessous aux répertoires d'inclusion supplémentaires 

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include

à cet emplacement, il y a un fichier appelé "yvals.h" qui contient la définition de _NOEXCEPT 

0
suraj kumar