Add wxCHECK_CXX_STD() and use it to test for C++17 and C++20

Unlike direct tests of __cplusplus, using this macro also works with
(recent enough, i.e. MSVS 2015.3 or later) MSVC versions, even if
/Zc:__cplusplus is not used.

This simplifies some checks and makes some other ones (notably the check
for C++20 used before wxALLOW_COMBINING_ENUMS macro definition) work
with MSVC versions with C++20 support as intended.
This commit is contained in:
Vadim Zeitlin
2022-05-11 16:57:18 +01:00
parent d311a07b7a
commit 2ba9007d0e
6 changed files with 46 additions and 8 deletions

View File

@@ -216,6 +216,24 @@
#define __USE_W32_SOCKETS
#endif
#if defined(_MSVC_LANG)
/*
We want to always use the really supported C++ standard when using MSVC
recent enough to define _MSVC_LANG, even if /Zc:__cplusplus option is not
used, but unfortunately we can't just redefine __cplusplus as _MSVC_LANG
because this is not allowed by the standard and, worse, doesn't work in
practice (it results in a warning and nothing else).
So, instead, we define a macro for testing __cplusplus which also works in
this case.
*/
#define wxCHECK_CXX_STD(ver) (_MSVC_LANG >= (ver))
#elif defined(__cplusplus)
#define wxCHECK_CXX_STD(ver) (__cplusplus >= (ver))
#else
#define wxCHECK_CXX_STD(ver) 0
#endif
/* ---------------------------------------------------------------------------- */
/* check for native bool type and TRUE/FALSE constants */
/* ---------------------------------------------------------------------------- */
@@ -302,7 +320,7 @@ typedef short int WXTYPE;
/* wxFALLTHROUGH is used to notate explicit fallthroughs in switch statements */
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
#if wxCHECK_CXX_STD(201703L)
#define wxFALLTHROUGH [[fallthrough]]
#elif __cplusplus >= 201103L && defined(__has_warning) && WX_HAS_CLANG_FEATURE(cxx_attributes)
#define wxFALLTHROUGH [[clang::fallthrough]]
@@ -1303,7 +1321,7 @@ typedef double wxDouble;
for doing this, that do the same thing as would happen without them, but
without the warnings.
*/
#if defined(__cplusplus) && (__cplusplus >= 202002L)
#if wxCHECK_CXX_STD(202002L)
#define wxALLOW_COMBINING_ENUMS_IMPL(en1, en2) \
inline int operator|(en1 v1, en2 v2) \
{ return static_cast<int>(v1) | static_cast<int>(v2); } \

View File

@@ -145,7 +145,7 @@ inline wxEventFunction wxEventFunctionCast(void (wxEvtHandler::*func)(T&))
// a type of wxEvtHandler method. But with C++17 this doesn't work when the
// handler is a noexcept function, so we need to cast it to a noexcept function
// pointer first.
#if __cplusplus >= 201703L
#if wxCHECK_CXX_STD(201703L)
namespace wxPrivate
{

View File

@@ -59,7 +59,7 @@
Things are simple with C++11: we have everything we need in std.
Eventually we will only have this section and not the legacy stuff below.
*/
#if __cplusplus >= 201103
#if wxCHECK_CXX_STD(201103)
#define wxFinite(x) std::isfinite(x)
#define wxIsNaN(x) std::isnan(x)
#else /* C++98 */
@@ -139,7 +139,7 @@ inline int wxRound(double x)
wxASSERT_MSG(x > double(INT_MIN) - 0.5 && x < double(INT_MAX) + 0.5,
"argument out of supported range");
#if __cplusplus >= 201103
#if wxCHECK_CXX_STD(201103)
return int(std::lround(x));
#elif defined(HAVE_ROUND) || wxCHECK_VISUALC_VERSION(12)
return int(lround(x));
@@ -153,7 +153,7 @@ inline int wxRound(float x)
wxASSERT_MSG(x > float(INT_MIN) && x < float(INT_MAX),
"argument out of supported range");
#if __cplusplus >= 201103
#if wxCHECK_CXX_STD(201103)
return int(std::lround(x));
#elif defined(HAVE_ROUND) || wxCHECK_VISUALC_VERSION(12)
return int(lroundf(x));

View File

@@ -180,7 +180,7 @@ extern unsigned long android_wcstoul(const wchar_t *nptr, wchar_t **endptr, int
#define wxCRT_StrtoullW _wcstoui64
#else
/* Both of these functions are implemented in C++11 compilers */
#if defined(__cplusplus) && __cplusplus >= 201103L
#if wxCHECK_CXX_STD(201103L)
#ifndef HAVE_STRTOULL
#define HAVE_STRTOULL
#endif

View File

@@ -1516,6 +1516,26 @@ typedef double wxDouble;
/** @addtogroup group_funcmacro_misc */
//@{
/**
Returns @true if the compiler being used supports the given C++ version.
The @a stdver parameter uses the same values as the standard @c __cplusplus
macro, i.e.
- 201103L for C++11
- 201402L for C++14
- 201703L for C++17
- 202002L for C++20
Using this macro also works with MSVC, even when @c /Zc:__cplusplus option
is not used, unlike checking for the value of @c __cplusplus directly.
@since 3.1.7
@header{wx/defs.h}
*/
#define wxCHECK_CXX_STD(stdver)
/**
This macro can be used in a class declaration to disable the generation of
default assignment operator.

View File

@@ -133,7 +133,7 @@ static void TestAssertHandler(const wxString& file,
// so we'd just die without any useful information -- abort instead.
abortReason << assertMessage << wxASCII_STR(" in a worker thread.");
}
#if __cplusplus >= 201703L || wxCHECK_VISUALC_VERSION(14)
#if wxCHECK_CXX_STD(201703L)
else if ( uncaught_exceptions() )
#else
else if ( uncaught_exception() )