c++ - Cómo lidiar con noexcept en Visual Studio
visual-studio-2012 c++11 (10)
"noexcept" solo es compatible desde Visual Studio 2015 (como se indica aquí: https://msdn.microsoft.com/en-us/library/wfa0edys.aspx ). He utilizado el siguiente código con Visual Studio 2013 (derivado de los ejemplos anteriores):
#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
Estoy intentando crear una excepción personalizada que se deriva de std::exception
y anula what()
. Al principio, lo escribí así:
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();
}
};
Esto funciona bien en VS2012, pero no se compila en GCC 4.8 con -std=c++11
:
error: especificador de tiro más flexible para ''virtual const char * UserException :: what () const''
Entonces agrego noexcept
:
virtual const char* what() const noexcept override
Esto funciona bien en GCC, pero no se compila en Visual Studio (porque VS 2012 no admite noexcept
):
error C3646: ''noexcept'': especificador de anulación desconocido
¿Cuál es la forma recomendada de lidiar con esto? Quiero el mismo código para compilar con ambos compiladores y estoy usando las características de C ++ 11, por lo que no puedo compilar con diferentes -std
.
Agregue las siguientes líneas en su código en Visual Studio:
#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif
El noexcept es una de las "carencias" más fáciles de MSVC: simplemente use la macro _NOEXCEPT
que en MSVC2013 se define en yvals.h.
Esta comprobación funciona para ver si noexcept
es compatible:
// 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
Lo anterior funciona con Clang, GCC y MSVC.
La otra forma de hacerlo es crear un archivo de encabezado e incluirlo si es necesario en su código fuente que debería compilarse mediante gcc, vc o 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
=============================================== ===
PS> no cubre caso no salvo (falso) pero funciona bien para VC2010,2012,2013, gcc 4.9
Lo que he usado recientemente es lo siguiente:
#ifdef _MSC_VER
#define NOEXCEPT _NOEXCEPT
#else
#define NOEXCEPT noexcept
#endif
y luego solo use NOEXCEPT
todas partes.
Parece que el antiguo throw()
(obsoleto en C ++ 11) funciona en ambos compiladores. Así que cambié el código a:
virtual const char* what() const throw() override
Usa una macro
#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
Y luego define la función como
virtual const char* what() const NOEXCEPT override
También puede modificar eso para permitir noexcept
en versiones posteriores de VS verificando el valor de _MSC_VER
; para VS2012 el valor es 1600.
use BOOST_NOEXCEPT
en <boost/config.hpp>
La biblioteca de configuración de impulso se diseñó para problemas de compatibilidad como este. De acuerdo con el documento :
Si se define
BOOST_NO_CXX11_NOEXCEPT
(es decir, compiladores que cumplen con C ++ 03) estas macros se definen como:
#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
no está definido (es decir, compiladores que cumplen con C ++ 11) se definen como:
#define BOOST_NOEXCEPT noexcept #define BOOST_NOEXCEPT_OR_NOTHROW noexcept #define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate)) #define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression))
Muchas de las otras respuestas aquí tienen una implementación similar, pero esta biblioteca es más limpia, mejor probada, y hará lo correcto cuando se actualice su compilador. Recomiendo mirar la biblioteca de configuración de boost en general para otras características, especialmente en este momento de flujo de idioma y niveles variables de soporte entre los compiladores.
#IF
s puede funcionar, aunque sea un poco hacky.
Podrías hacer esto:
#if __GNUG__
virtual const char* what() const noexcept override
#else
virtual const char* what() const override
#endif
//method body