it-swarm.com.de

Umgang mit noexcept in Visual Studio

Ich versuche, eine benutzerdefinierte Ausnahme zu erstellen, die von std::exception abgeleitet ist und what() überschreibt. Zuerst schrieb ich es so:

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();
    }
};

Das funktioniert gut in VS2012, aber es wird in GCC 4.8 nicht mit -std=c++11 kompiliert:

fehler: Lockerer Wurfspezifizierer für 'virtual const char * UserException :: what () const'

Also füge ich noexcept hinzu:

virtual const char* what() const noexcept override

Dies funktioniert problemlos in GCC, wird jedoch in Visual Studio nicht kompiliert (da VS 2012 noexcept nicht unterstützt):

fehler C3646: 'noexcept': unbekannter Überschreibungsbezeichner

Was ist der empfohlene Weg, um damit umzugehen? Ich möchte, dass derselbe Code mit beiden Compilern kompiliert wird. Ich verwende C++ 11-Funktionen. Ich kann also nicht mit verschiedenen -std-Dateien kompilieren.

43
svick

Verwenden Sie ein Makro

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

Und dann definieren Sie die Funktion als

virtual const char* what() const NOEXCEPT override

Sie können dies auch ändern, um noexcept in späteren Versionen von VS zuzulassen, indem Sie den Wert von _MSC_VER überprüfen. für VS2012 ist der Wert 1600.

43
Praetorian

"noexcept" wird nur seit Visual Studio 2015 unterstützt (wie hier angegeben: https://msdn.Microsoft.com/en-us/library/wfa0edys.aspx ) ..__ Visual Studio 2013 (abgeleitet von den obigen Beispielen):

#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
15
ivan.ukr

Diese Prüfung funktioniert, um zu sehen, ob noexcept unterstützt wird:

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

Das oben genannte funktioniert mit Clang, GCC und MSVC.

12
marton78

verwenden Sie BOOST_NOEXCEPT in <boost/config.hpp>

Die Boost-Konfigurationsbibliothek wurde für Kompatibilitätsprobleme wie diese entwickelt. Nach dem Dokument :

Wenn BOOST_NO_CXX11_NOEXCEPT definiert ist (d. H. C++ 03-kompatible Compiler), sind diese Makros wie folgt definiert:

    #define BOOST_NOEXCEPT
    #define BOOST_NOEXCEPT_OR_NOTHROW throw()
    #define BOOST_NOEXCEPT_IF(Predicate)
    #define BOOST_NOEXCEPT_EXPR(Expression) false

Wenn BOOST_NO_CXX11_NOEXCEPT nicht definiert ist (d. H. C++ 11-kompatible Compiler), werden sie definiert als:

    #define BOOST_NOEXCEPT noexcept
    #define BOOST_NOEXCEPT_OR_NOTHROW noexcept
    #define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate))
    #define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression))

Viele der anderen Antworten haben eine ähnliche Implementierung, aber diese Bibliothek ist sauberer, besser getestet und wird das Richtige tun, wenn der Compiler aktualisiert wird. Ich empfehle, die Boost-Konfigurationsbibliothek im Allgemeinen nach anderen Funktionen zu durchsuchen, insbesondere in dieser Zeit des Sprachflusses und der unterschiedlichen Unterstützungsniveaus der Compiler.

9
evan

Das noexcept ist eines der am einfachsten zu behandelnden "Mängel" von MSVC: Verwenden Sie einfach das Makro _NOEXCEPT, das unter MSVC2013 in yvals.h definiert ist.

3
patlecat

Fügen Sie Ihrem Code in Visual Studio die folgenden Zeilen hinzu:

#ifdef _NOEXCEPT
#define noexcept _NOEXCEPT
#endif
3

Was ich kürzlich verwendet habe, ist folgendes:

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

und dann einfach überall NOEXCEPT verwenden.

2
ivan.ukr

Es scheint, dass die alte throw() (in C++ 11 nicht mehr empfohlen) in beiden Compilern funktioniert. Also habe ich den Code geändert in:

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

Die andere Möglichkeit besteht darin, die Header-Datei zu erstellen und sie gegebenenfalls in den Quellcode aufzunehmen, die von gcc, vc oder clang kompiliert werden sollte.

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> behandelt den Fall Noexcept (false) Nicht, funktioniert jedoch für VC2010,2012,2013, gcc 4.9

1
Alexei Valyaev

#IFs kann funktionieren, auch wenn sie ein bisschen hackig sind.

Sie könnten das einfach tun:

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

fügen Sie den zusätzlichen Pfad zu den zusätzlichen Include-Verzeichnissen hinzu 

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

an dieser Stelle befindet sich eine Datei mit dem Namen "yvals.h", die die Definition von _NOEXCEPT enthält 

0
suraj kumar