web-dev-qa-db-ja.com

Visual Studioでnoexceptを処理する方法

_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」の緩やかなスロー指定子

そこで、noexceptを追加します。

_virtual const char* what() const noexcept override
_

これはGCCでは正常に機能しますが、Visual Studioではコンパイルされません(VS 2012はnoexceptをサポートしないため):

エラーC3646: 'noexcept':不明なオーバーライド指定子

これに対処するための推奨される方法は何ですか?同じコードを両方のコンパイラでコンパイルしたいのですが、C++ 11機能を使用しているため、異なる_-std_でコンパイルできません。

44
svick

マクロを使用する

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

そして、関数を次のように定義します

virtual const char* what() const NOEXCEPT override

_MSC_VERの値をチェックして、VSの以降のバージョンでnoexceptを許可するように変更することもできます。 VS2012の場合、値は1600です。

43
Praetorian

「noexcept」はVisual Studio 2015以降でのみサポートされています(ここで説明されているように、 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
16
ivan.ukr

このチェックは、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で動作します。

12
marton78

つかいます BOOST_NOEXCEPT in <boost/config.hpp>

ブースト設定ライブラリは、このような互換性の問題のために設計されました。 ドキュメント によると:

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))

ここでの他の回答の多くは同様の実装を持っていますが、このライブラリはよりクリーンで、よりよくテストされており、コンパイラがアップグレードされたときに正しいことを行います。他の機能については、特にこの時期の言語の流動性とコンパイラー間でのさまざまなレベルのサポートのために、一般にブースト構成ライブラリーを調べることをお勧めします。

10
evan

Visual Studioのコードに次の行を追加します。

#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif
4

noexceptは、MSVCの最も簡単な「不足」の1つです。MSVC2013でyvals.hで定義されているマクロ_NOEXCEPTを使用するだけです。

3
patlecat

最近使用したのは次のとおりです。

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

そして、どこでもNOEXCEPTを使用します。

2
ivan.ukr

古いthrow()(C++ 11で非推奨)は両方のコンパイラで動作するようです。そこで、コードを次のように変更しました。

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

他の方法は、ヘッダーファイルを作成し、必要に応じて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)をカバーしていませんが、VC2010、2012、2013、gcc 4.9で正常に動作します

1
Alexei Valyaev

#IFsは、少しハッキーでも機能する場合があります。

あなたはこれを行うことができます:

#if __GNUG__
virtual const char* what() const noexcept override
#else
virtual const char* what() const override
#endif
//method body
0
It'sNotALie.

追加のインクルードディレクトリに以下のパスを追加します

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

この場所には、_NOEXCEPTの定義を含む「yvals.h」というファイルがあります。

0
suraj kumar