47

我正在尝试创建一个派生自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 中工作正常,但它不能在 GCC 4.8 中编译-std=c++11

错误:'virtual const char* UserException::what() const'的更宽松的抛出说明符</p>

所以我补充说noexcept

virtual const char* what() const noexcept override

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

错误 C3646:“noexcept”:未知覆盖说明符

处理此问题的推荐方法是什么?我希望使用两个编译器编译相同的代码,并且我正在使用 C++11 功能,所以我不能使用不同的-std.

4

11 回答 11

45

使用宏

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

然后将函数定义为

virtual const char* what() const NOEXCEPT override

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

于 2013-08-22T18:05:39.903 回答
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
于 2015-10-23T09:12:15.410 回答
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

以上适用于 Clang、GCC 和 MSVC。

于 2014-01-10T07:18:54.647 回答
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

如果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 配置库的其他功能,尤其是在这个语言不断变化和编译器支持水平不同的时代。

于 2015-12-15T12:27:58.960 回答
3

noexcept是 MSVC 最容易处理的“缺陷”之一:只需使用在 yvals.h 中定义的 MSVC2013 下的宏_NOEXCEPT

于 2014-04-09T10:05:11.670 回答
3

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

#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif
于 2014-10-05T09:58:51.897 回答
2

我最近使用的是以下内容:

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

然后NOEXCEPT随处使用。

于 2015-12-01T21:37:26.817 回答
1

似乎旧的throw()(在 C++11 中已弃用)在两种编译器中都有效。所以我将代码更改为:

virtual const char* what() const throw() override
于 2013-08-22T18:06:02.967 回答
1

另一种解决方法是创建头文件,并在必要时将其包含在应由 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

==================================================== ===

PS> 不包括 case noexcept(false) 但适用于 VC2010,2012,2013, gcc 4.9

于 2015-12-01T20:05:02.673 回答
0

#IFs 可能会工作,即使有点hacky。

你可以这样做:

#if __GNUG__
virtual const char* what() const noexcept override
#else
virtual const char* what() const override
#endif
//method body
于 2013-08-22T18:05:52.977 回答
0

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

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include

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

于 2018-12-21T11:34:06.670 回答