How to deal with noexcept in Visual Studio

35,785

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
Share:
35,785

Related videos on Youtube

svick
Author by

svick

Updated on July 09, 2022

Comments

  • svick
    svick almost 2 years

    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.

  • svick
    svick almost 11 years
    According to this video (look at the table at 58:00), noexcept won't be supported in VS2013.
  • svick
    svick almost 11 years
    Also, does it make sense to use #define NOEXCEPT throw() for the VS version?
  • Praetorian
    Praetorian almost 11 years
    @svick There is a small difference in behavior between the two. Throwing from a function marked throw() will call std::unexpected, whereas std::terminate will be called if it were marked noexcept; but in your use case the two should be equivalent. However, the MSDN page for std::exception doesn't indicate what() is marked throw(), so you may run into warnings or errors if you add the exception specification to the overriden function.
  • svick
    svick about 10 years
    But 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
    patlecat almost 10 years
    facepalm 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
    StarShine over 9 years
    This is wrong. You are defining a macro with the same literal as a reserved keyword, which is forbidden.
  • Anant Simran Singh
    Anant Simran Singh over 9 years
    This works in VS to introduce compatibility between two versions.
  • StarShine
    StarShine over 9 years
    Even 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
    idbrii over 9 years
    Wouldn'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
    wilx over 9 years
    But that is not the same thing. Does it remove the looser throw specifier for ‘virtual const char* UserException::what() const’ error?
  • svick
    svick over 9 years
    @VáclavZeman Yeah, as far as I remember, this actually worked for me.
  • marton78
    marton78 almost 9 years
    Well, MSVC 2010 doesn't have noexcept, does it? Its _MSC_VER is 1600, which is smaller than 1800, therefore NOEXCEPT should expand to nothing. What is the problem you are experiencing?
  • Alex
    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
    Alexei Valyaev over 8 years
    The 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
    Emil Styrke over 8 years
    180021114 seems to be VS2013, which does not support noexcept. ivan.ukr's value of 190023026 works better for me.
  • ivan.ukr
    ivan.ukr over 5 years
    Create some header file, include it where you plan to use all that.