How to deal with noexcept in Visual Studio
Solution 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.
Solution 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
Solution 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.
Solution 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.
Solution 5
Add the following lines in your code in Visual Studio:
#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif
Related videos on Youtube
svick
Updated on July 09, 2022Comments
-
svick almost 2 years
I'm trying to create a custom exception that derives from
std::exception
and overrideswhat()
. 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
. -
svick almost 11 yearsAccording to this video (look at the table at 58:00),
noexcept
won't be supported in VS2013. -
svick almost 11 yearsAlso, does it make sense to use
#define NOEXCEPT throw()
for the VS version? -
Praetorian almost 11 years@svick There is a small difference in behavior between the two. Throwing from a function marked
throw()
will callstd::unexpected
, whereasstd::terminate
will be called if it were markednoexcept
; but in your use case the two should be equivalent. However, the MSDN page forstd::exception
doesn't indicatewhat()
is markedthrow()
, so you may run into warnings or errors if you add the exception specification to the overriden function. -
svick about 10 yearsBut I wasn't looking for a solution that works only in VS, I was looking for a solution that works everywhere (or at least both in VS and GCC).
-
patlecat almost 10 yearsfacepalm Well @svick then use the macro I just gave you and combine it with the
noexcept
from C++11 and voilà you'll have a solution that works everywhere! :D -
StarShine over 9 yearsThis is wrong. You are defining a macro with the same literal as a reserved keyword, which is forbidden.
-
Anant Simran Singh over 9 yearsThis works in VS to introduce compatibility between two versions.
-
StarShine over 9 yearsEven in Visual Studio versions before C++11, noexcept is a reserved keyword. You'll get a warning during compilation. I suggest to use capital NOEXCEPT in this case.
-
idbrii over 9 yearsWouldn't it be better to define _NOEXCEPT to noexcept if it's undefined? (So you'd use VS's version when compiling in MSVC and C++11's version in other compilers.)
-
wilx over 9 yearsBut that is not the same thing. Does it remove the
looser throw specifier for ‘virtual const char* UserException::what() const’
error? -
svick over 9 years@VáclavZeman Yeah, as far as I remember, this actually worked for me.
-
marton78 almost 9 yearsWell, MSVC 2010 doesn't have
noexcept
, does it? Its_MSC_VER
is1600
, which is smaller than1800
, thereforeNOEXCEPT
should expand to nothing. What is the problem you are experiencing? -
Alex almost 9 years
warning C4067: unexpected tokens following preprocessor directive - expected a newline
. It looks like ` __has_feature(cxx_noexcept)` is confusing it for some reason. When I remove that it works fine. Edit: I realize now I was treating warnings as errors, and this was just a warning. If I suppress 4067 it works after all. -
Alexei Valyaev over 8 yearsThe advantage you can start use noexcept and after moving on VC 2015 just remove header in your code without impact: #include "no_except_work_around.h"
-
Emil Styrke over 8 years180021114 seems to be VS2013, which does not support
noexcept
. ivan.ukr's value of 190023026 works better for me. -
ivan.ukr over 5 yearsCreate some header file, include it where you plan to use all that.