Подтвердить что ты не робот

Как справиться с noexcept в Visual Studio

Я пытаюсь создать настраиваемое исключение, которое происходит от 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:

error: looser throw specifier для 'virtual const char * UserException:: what() const

Итак, я добавляю noexcept:

virtual const char* what() const noexcept override

Это отлично работает в GCC, но не компилируется в Visual Studio (потому что VS 2012 не поддерживает noexcept):

ошибка C3646: "noexcept": неизвестный спецификатор переопределения

Каков рекомендуемый способ справиться с этим? Я хочу, чтобы один и тот же код компилировался с обоими компиляторами, и я использую С++ 11, поэтому я не могу скомпилировать с помощью -std.

4b9b3361

Ответ 1

Используйте макрос

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

И затем определите функцию как

virtual const char* what() const NOEXCEPT override

Вы также можете изменить это, чтобы разрешить noexcept в более поздних версиях VS, проверив значение _MSC_VER; для VS2012 значение равно 1600.

Ответ 2

"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

Ответ 3

Эта проверка проверяет, поддерживается ли 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.

Ответ 4

использовать BOOST_NOEXCEPT в <boost/config.hpp>

Библиотека конфигурации boost была разработана для таких проблем совместимости. Согласно документу:

Если BOOST_NO_CXX11_NOEXCEPT определен (т.е. компиляторы, совместимые с С++ 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 не определен (то есть компиляторы, совместимые с С++ 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 config в целом для других функций, особенно в это время языкового потока и различных уровней поддержки среди компиляторов.

Ответ 5

noexcept является одним из самых простых "недостатков" MSVC: просто используйте макрос _NOEXCEPT, который под MSVC2013 определен в yvals.h.

Ответ 6

Добавьте в свой код в Visual Studio следующие строки:

#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif

Ответ 7

То, что я недавно использовал, следующее:

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

а затем просто используйте NOEXCEPT всюду.

Ответ 8

Кажется, что старый throw() (устаревший в С++ 11) работает в обоих компиляторах. Поэтому я изменил код на:

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

Ответ 9

Другой способ обойти - создать заголовочный файл и включить его, если необходимо, в исходный код, который должен быть скомпилирован 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 (ложь) но отлично работает для VC2010,2012,2013, gcc 4.9

Ответ 10

#IF может работать, даже если бит взломан.

Вы могли бы просто сделать это:

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

Ответ 11

добавьте следующий путь к дополнительным каталогам включения

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

в этом месте находится файл с именем "yvals.h", который содержит определение _NOEXCEPT