可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to create a custom exception that derives from std::exception
and overrides what()
. At first, I wrote it like this:
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(); } };
This works fine in VS2012, but it doesn't compile in GCC 4.8 with -std=c++11
:
error: looser throw specifier for ‘virtual const char* UserException::what() const’
So I add noexcept
:
virtual const char* what() const noexcept override
This works fine in GCC, but it doesn't compile in Visual Studio (because VS 2012 doesn't support noexcept
):
error C3646: 'noexcept' : unknown override specifier
What is the recommended way to deal with this? I want the same code to compile with both compilers and I'm using C++11 features, so I can't compile with different -std
.
回答1:
Use a macro
#ifndef _MSC_VER #define NOEXCEPT noexcept #else #define NOEXCEPT #endif
And then define the function as
virtual const char* what() const NOEXCEPT override
You could also modify that to allow noexcept
on later versions of VS by checking the value of _MSC_VER
; for VS2012 the value is 1600.
回答2:
"noexcept" is only supported since the Visual Studio 2015 (as stated here: https://msdn.microsoft.com/en-us/library/wfa0edys.aspx). I have used following code with Visual Studio 2013 (derived from above examples):
#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
回答3:
This check works to see if noexcept
is supported:
// 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
The above works with Clang, GCC and MSVC.
回答4:
use BOOST_NOEXCEPT
in <boost/config.hpp>
The boost config library was designed for compatibility issues like this. According to the doc:
If BOOST_NO_CXX11_NOEXCEPT
is defined (i.e. C++03 compliant compilers) these macros are defined as:
#define BOOST_NOEXCEPT #define BOOST_NOEXCEPT_OR_NOTHROW throw() #define BOOST_NOEXCEPT_IF(Predicate) #define BOOST_NOEXCEPT_EXPR(Expression) false
If BOOST_NO_CXX11_NOEXCEPT
is not defined (i.e. C++11 compliant compilers) they are defined as:
#define BOOST_NOEXCEPT noexcept #define BOOST_NOEXCEPT_OR_NOTHROW noexcept #define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate)) #define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression))
Many of the other answers here have a similar implementation but this library is cleaner, better tested, and will do the right thing when your compiler is upgraded. I recommend looking at the boost config library in general for other features, especially in this time of language flux and varying levels of support among compilers.
回答5:
The noexcept is one of the easiest "lacks" of MSVC to deal with: Just use the macro _NOEXCEPT
which under MSVC2013 is defined in yvals.h .
回答6:
Add the following lines in your code in Visual Studio:
#ifdef _NOEXCEPT #define noexcept _NOEXCEPT #endif
回答7:
What I've recently used is following:
#ifdef _MSC_VER #define NOEXCEPT _NOEXCEPT #else #define NOEXCEPT noexcept #endif
and then just use NOEXCEPT
everywhere.
回答8:
It seems that the old throw()
(deprecated in C++11) works in both compilers. So I changed the code to:
virtual const char* what() const throw() override
回答9:
The other way to go around is create header file and include it if necessary in your source code that should be compile by gcc, vc,or 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> doesn't cover case noexcept(false) but works fine for VC2010,2012,2013, gcc 4.9
回答10:
#IF
s may work, even if a bit hacky.
You could just do this:
#if __GNUG__ virtual const char* what() const noexcept override #else virtual const char* what() const override #endif //method body