如何在Visual Studio中处理noexcept

How to deal with noexcept in Visual Studio

本文关键字:处理 noexcept Studio Visual      更新时间:2023-10-16

我正在尝试创建一个从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();
    }
};

这在VS2012中运行良好,但在带有-std=c++11:的GCC 4.8中无法编译

错误:"virtual const char*UserException::what()const"的抛出说明符更宽松

所以我添加了noexcept:

virtual const char* what() const noexcept override

这在GCC中运行良好,但在Visual Studio中无法编译(因为VS 2012不支持noexcept):

错误C3646:"noexcept":未知的重写说明符

建议的处理方法是什么?我希望用两个编译器编译相同的代码,并且我使用C++11功能,所以我不能用不同的-std编译。

使用宏

#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif

然后将函数定义为

virtual const char* what() const NOEXCEPT override

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

只有在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

此检查用于查看是否支持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

以上与Clang、GCC和MSVC合作。

<boost/config.hpp> 中使用BOOST_NOEXCEPT

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

如果未定义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))

这里的许多其他答案都有类似的实现,但这个库更干净,测试更好,并且在编译器升级时会做正确的事情。我建议查看boost配置库的其他功能,尤其是在语言不断变化和编译器之间支持程度不同的情况下。

noexcept是MSVC最容易处理的"缺点"之一:只需使用宏_NOEXCEPT,该宏在MSVC2013下在yvals.h中定义。

在Visual Studio中的代码中添加以下行:

#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif

我最近使用的是:

#ifdef _MSC_VER
#define NOEXCEPT _NOEXCEPT
#else
#define NOEXCEPT noexcept
#endif

然后在任何地方都使用CCD_ 15。

似乎旧的throw()(在C++11中已弃用)适用于这两个编译器。所以我把代码改成:

virtual const char* what() const throw() override

另一种方法是创建头文件,并在必要时将其包含在应该由gcc、vc或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>不包括案件noexcept(false)但适用于VC201020122013,gcc 4.9

#IF可能会工作,即使有点麻烦。

你可以这样做:

#if __GNUG__
virtual const char* what() const noexcept override
#else
virtual const char* what() const override
#endif
//method body

将以下路径添加到其他包含目录

C:Program Files (x86)Microsoft Visual Studio 14.0VCinclude

在这个位置有一个名为"yvals.h"的文件,其中包含_NOEXCEPT 的定义