如何在Visual Studio中处理noexcept

svi*_*ick 45 c++ noexcept c++11 visual-studio-2012

我正在尝试创建一个源自std::exception和覆盖的自定义异常what().起初,我这样写:

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();
    }
};
Run Code Online (Sandbox Code Playgroud)

这在VS2012中工作正常,但它不能在GCC 4.8中编译-std=c++11:

错误:'virtualos char*UserException :: what()const'的looser throw说明符

所以我补充说noexcept:

virtual const char* what() const noexcept override
Run Code Online (Sandbox Code Playgroud)

这在GCC中工作正常,但它不能在Visual Studio中编译(因为VS 2012不支持noexcept):

错误C3646:'noexcept':未知的覆盖说明符

建议的方法是什么?我希望使用两个编译器编译相同的代码,并且我正在使用C++ 11功能,因此我无法使用不同的编译-std.

Pra*_*ian 44

使用宏

#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
Run Code Online (Sandbox Code Playgroud)

然后将函数定义为

virtual const char* what() const NOEXCEPT override
Run Code Online (Sandbox Code Playgroud)

您也可以noexcept通过检查值的值来修改它以允许在更高版本的VS上_MSC_VER; 对于VS2012,该值为1600.

  • 根据[此视频(见表58:00)](http://channel9.msdn.com/Events/Build/2013/2-306),VS2013不支持`noexcept`. (2认同)
  • 另外,在VS版本中使用#define NOEXCEPT throw()是否有意义? (2认同)
  • @svick两者之间的行为存在细微差别.从标记为`throw()`的函数抛出将调用`std :: unexpected`,而如果标记为`noexcept`则调用`std :: terminate`; 但在你的用例中,两者应该是等价的.但是,[std :: exception`的[MSDN页面](http://msdn.microsoft.com/en-us/library/c4ts6d5a.aspx)并不表示`what()`标记为`throw() `,因此如果将异常规范添加到overriden函数,您可能会遇到警告或错误. (2认同)

iva*_*ukr 16

自从Visual Studio 2015以来,仅支持"noexcept"(如此处所述:https://msdn.microsoft.com/en-us/library/wfa0edys.aspx ).我在Visual Studio 2013中使用了以下代码(源自上面的示例):

#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
Run Code Online (Sandbox Code Playgroud)


mar*_*n78 12

此检查用于查看是否noexcept支持:

// 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
Run Code Online (Sandbox Code Playgroud)

以上内容适用于Clang,GCC和MSVC.


eva*_*van 10

BOOST_NOEXCEPT<boost/config.hpp>

boost配置库是为这样的兼容性问题而设计的.根据文件:

如果BOOST_NO_CXX11_NOEXCEPT已定义(即符合C++ 03的编译器),则这些宏定义为:

    #define BOOST_NOEXCEPT
    #define BOOST_NOEXCEPT_OR_NOTHROW throw()
    #define BOOST_NOEXCEPT_IF(Predicate)
    #define BOOST_NOEXCEPT_EXPR(Expression) false
Run Code Online (Sandbox Code Playgroud)

如果BOOST_NO_CXX11_NOEXCEPT未定义(即符合C++ 11的编译器),则将它们定义为:

    #define BOOST_NOEXCEPT noexcept
    #define BOOST_NOEXCEPT_OR_NOTHROW noexcept
    #define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate))
    #define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression))
Run Code Online (Sandbox Code Playgroud)

这里的许多其他答案都有类似的实现,但是这个库更清晰,测试更好,并且在升级编译器时会做正确的事情.我建议一般查看boost配置库以获取其他功能,特别是在语言流量和编译器支持程度不同的时候.