| GL Studio C++ Runtime API

gls_cpp_lang_support.h
Go to the documentation of this file.
1/*! \file
2 \brief Macros and helper code to determine what subset of C++11/14/17 is available.
3
4 \par Copyright Information
5
6 Copyright (c) 2016 The DiSTI Corporation.<br>
7 11486 Corporate Blvd; Suite 190<br>
8 Orlando, Florida 32817<br>
9 USA<br>
10 <br>
11 All rights reserved.<br>
12
13 This Software contains proprietary trade secrets of DiSTI and may not be
14 reproduced, in whole or part, in any form, or by any means of electronic,
15 mechanical, or otherwise, without the written permission of DiSTI. Said
16 permission may be derived through the purchase of applicable DiSTI product
17 licenses which detail the distribution rights of this content and any
18 Derivative Works based on this or other copyrighted DiSTI Software.
19
20 NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21 AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22 PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23 AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25 PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26
27 LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28 IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29 INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30 DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31 INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32 INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34 EXCEED FIVE DOLLARS (US$5.00).
35
36 The aforementioned terms and restrictions are governed by the laws of the
37 State of Florida and the United States of America.
38*/
39
40#ifndef INCLUDED_GLS_CPP_LANG_SUPPORT_H
41#define INCLUDED_GLS_CPP_LANG_SUPPORT_H
42
43// Conditional C++11/14 support
44//
45// We use a subset of C++11/14 features to improve efficiency and correctness of code.
46//
47// We attempt to detect compiler support, but for unusual configurations, it can be
48// enabled with project-level defines. Define DISTI_HAS_CPP11 to enable all features.
49// Enable specific features by defining any of the following:
50//
51// DISTI_HAS_RVAL_REFS // For rvalue references
52// DISTI_HAS_METHOD_OVERRIDE // For "override" and "final" keywords
53// DISTI_HAS_NOEXCEPT // For "noexcept" keyword
54// DISTI_HAS_SPECIAL_MEM_FUN_DEL // For "= delete"
55// DISTI_HAS_TYPE_TRAITS // For compile-time checking via type-traits
56// DISTI_HAS_STATIC_ASSERT // For static_assert support
57// DISTI_HAS_DEPRECATED_ATTRIBUTE // For [[deprecated("why")]] attribute
58// DISTI_HAS_USER_DEFINED_LITERALS // For operator""_myLiteral
59//
60// If our detection is incorrect, override it with a corresponding "NO" define:
61//
62// DISTI_NO_RVAL_REFS // For rvalue references
63// DISTI_NO_METHOD_OVERRIDE // For "override" and "final" keywords
64// DISTI_NO_NOEXCEPT // For "noexcept" keyword
65// DISTI_NO_SPECIAL_MEM_FUN_DEL // For "= delete"
66// DISTI_NO_TYPE_TRAITS // For compile-time checking via type-traits
67// DISTI_NO_STATIC_ASSERT // For static_assert support
68// DISTI_NO_DEPRECATED_ATTRIBUTE // For [[deprecated("why")]] attribute
69// DISTI_NO_USER_DEFINED_LITERALS // For operator""_myLiteral
70/////////////////////////////////////////////////////////////////////////////////////
71// Microsoft C++ Compiler -- https://msdn.microsoft.com/en-us/library/hh567368.aspx
72/////////////////////////////////////////////////////////////////////////////////////
73#if defined( _MSC_VER )
74# if _MSC_VER >= 1700 // >= VS2012
75# define DISTI_HAS_RVAL_REFS
76# define DISTI_HAS_METHOD_OVERRIDE
77# define DISTI_HAS_TYPE_TRAITS
78# define DISTI_HAS_STATIC_ASSERT
79# endif
80# if _MSC_VER >= 1800 // >= VS2013
81# define DISTI_HAS_SPECIAL_MEM_FUN_DEL
82# define DISTI_HAS_CPP11
83# endif
84# if _MSC_VER >= 1900 // >= VS2015
85# define DISTI_HAS_USER_DEFINED_LITERALS
86# endif
87# if _MSC_VER >= 1911 && __cplusplus >= 201402L // >= VS2017 15.3
88# define DISTI_HAS_NOEXCEPT
89# define DISTI_HAS_DEPRECATED_ATTRIBUTE
90# define DISTI_HAS_CPP14
91# endif
92
93////////////////////////////////////////////////////////////////////////////////
94// GCC versions -- https://gcc.gnu.org/projects/cxx-status.html#cxx11
95////////////////////////////////////////////////////////////////////////////////
96#elif defined( __GNUC__ ) && !defined( __clang__ )
97// __cpp_rvalue_references doesn't seem to be defined in GCC, despite the documentation, so we have an alternative check also
98# if __cpp_rvalue_references >= 200610 || ( ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 ) ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L ) )
99# define DISTI_HAS_RVAL_REFS
100# endif
101# if __cpp_static_assert >= 200410 && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L )
102# define DISTI_HAS_STATIC_ASSERT
103# endif
104# if( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 9 ) ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L )
105# define DISTI_HAS_USER_DEFINED_LITERALS
106# endif
107# if( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 7 ) ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L )
108# define DISTI_HAS_METHOD_OVERRIDE
109# define DISTI_HAS_NOEXCEPT
110# define DISTI_HAS_TYPE_TRAITS // This actually depends on which standard library is in use, but it's a safe bet.
111# define DISTI_HAS_CPP11
112# endif
113# if( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L )
114# define DISTI_HAS_SPECIAL_MEM_FUN_DEL
115# endif
116# if( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 9 ) ) && __cplusplus >= 201402L
117# define DISTI_HAS_DEPRECATED_ATTRIBUTE
118# define DISTI_HAS_CPP14
119# endif
120
121////////////////////////////////////////////////////////////////////////////////
122// Clang versions -- http://clang.llvm.org/cxx_status.html
123////////////////////////////////////////////////////////////////////////////////
124#elif defined( __clang__ )
125# if __has_feature( cxx_rvalue_references )
126# define DISTI_HAS_RVAL_REFS
127# define DISTI_HAS_CPP11 // Guess that if we have rvalue refs, we've got pretty solid C++11 support
128# endif
129# if __has_feature( cxx_override_control )
130# define DISTI_HAS_METHOD_OVERRIDE
131# endif
132# if __has_feature( cxx_noexcept )
133# define DISTI_HAS_NOEXCEPT
134# endif
135# if __has_feature( cxx_defaulted_functions ) && __has_feature( cxx_deleted_functions )
136# define DISTI_HAS_SPECIAL_MEM_FUN_DEL
137# endif
138# if __has_feature( cxx_static_assert )
139# define DISTI_HAS_STATIC_ASSERT
140# endif
141# if __has_feature( cxx_user_literals )
142# define DISTI_HAS_USER_DEFINED_LITERALS
143# endif
144# if( __clang_major__ > 3 || ( __clang_major__ == 3 && __clang_minor__ >= 4 ) ) && __cplusplus >= 201402L
145# define DISTI_HAS_DEPRECATED_ATTRIBUTE
146# define DISTI_HAS_CPP14
147# endif
148// This actually depends on which standard library is in use, but it's a safe bet.
149# define DISTI_HAS_TYPE_TRAITS
150#endif
151
152///////////////////////////////////////////////////////////////////////////////////////////////////
153// Shortcut for unrecognized compilers
154///////////////////////////////////////////////////////////////////////////////////////////////////
155// A single switch to enable everything since compiler is highly compliant
156// These macros can help with cross-platform portability
157#ifdef DISTI_HAS_CPP14
158/// Defines whether or not C++11 support is available.
159# define DISTI_HAS_CPP11
160/// Defines whether this compiler supports the C++14 deprecated attribute.
161# define DISTI_HAS_DEPRECATED_ATTRIBUTE
162#endif
163
164#ifdef DISTI_HAS_CPP11
165/// Macro to wrap code that should be excluded if C++11 support is not available.
166# define DISTI_IF_HAS_CPP11( x ) x
167/// Macro to wrap code that has two implementations, one for C++11 support and the other without.
168# define DISTI_IF_HAS_CPP11_ELSE( x, y ) x
169
170/// Defines whether or not this compiler supports move semantics.
171# define DISTI_HAS_RVAL_REFS
172/// Defines whether or not this compiler supports the override keyword.
173# define DISTI_HAS_METHOD_OVERRIDE
174/// Defines whether or not this compiler supports deleted functions.
175# define DISTI_HAS_SPECIAL_MEM_FUN_DEL
176/// Defines whether or not this compiler supports type traits.
177# define DISTI_HAS_TYPE_TRAITS
178/// Defines whether or not this compiler supports static assertion.
179# define DISTI_HAS_STATIC_ASSERT
180#else
181// Not fully C++11; some features may be enabled piecemeal
182// These macros can help with cross-platform portability
183
184/// Macro to wrap code that should be excluded if C++11 support is not available.
185# define DISTI_IF_HAS_CPP11( x )
186/// Macro to wrap code that has two implementations, one for C++11 support and the other without.
187# define DISTI_IF_HAS_CPP11_ELSE( x, y ) y
188#endif
189
190///////////////////////////////////////////////////////////////////////////////////////////////////
191// Individual C++11 features. See comment above on DISTI_NO_* vs. DISTI_HAS_* macros.
192///////////////////////////////////////////////////////////////////////////////////////////////////
193#if !defined( DISTI_NO_RVAL_REFS ) && defined( DISTI_HAS_RVAL_REFS )
194# include <utility>
195/// Macro to wrap std::move, removed on compilers that don't support it.
196# define DISTI_RVAL_MOVE( x ) std::move( x )
197/// Macro to wrap std::forward, removed on compilers that don't support it.
198# define DISTI_UREF_FORWARD( T, x ) std::forward<T>( x )
199/// Macro to wrap r-value reference, removed on platforms that don't support it.
200# define DISTI_UREF( T ) T&&
201/// Macro to wrap code that should be excluded if r-value references aren't supported.
202# define DISTI_IF_HAS_RVAL_REFS( x ) x
203/// Macro to wrap code that has two implementations, one for r-value reference support, and the other without.
204# define DISTI_IF_HAS_RVAL_REFS_ELSE( x, y ) x
205#else
206# undef DISTI_HAS_RVAL_REFS
207/// Macro to wrap std::move, removed on compilers that don't support it.
208# define DISTI_RVAL_MOVE( x ) x
209/// Macro to wrap std::forward, removed on compilers that don't support it.
210# define DISTI_UREF_FORWARD( T, x ) x
211/// Macro to wrap r-value reference, removed on platforms that don't support it.
212# define DISTI_UREF( T ) const T&
213/// Macro to wrap code that should be excluded if r-value references aren't supported.
214# define DISTI_IF_HAS_RVAL_REFS( x )
215/// Macro to wrap code that has two implementations, one for r-value reference support, and the other without.
216# define DISTI_IF_HAS_RVAL_REFS_ELSE( x, y ) y
217#endif
218
219///////////////////////////////////////////////////////////////////////////////////////////////////
220#if !defined( DISTI_NO_METHOD_OVERRIDE ) && defined( DISTI_HAS_METHOD_OVERRIDE )
221/// Macro to wrap the override keyword, removed on compilers that don't support it.
222# define DISTI_METHOD_OVERRIDE override
223/// Macro to wrap the final keyword, removed on compilers that don't support it.
224# define DISTI_FINAL final
225#else
226# undef DISTI_HAS_METHOD_OVERRIDE
227/// Macro to wrap the override keyword, removed on compilers that don't support it.
228# define DISTI_METHOD_OVERRIDE
229/// Macro to wrap the final keyword, removed on compilers that don't support it.
230# define DISTI_FINAL
231#endif
232
233///////////////////////////////////////////////////////////////////////////////////////////////////
234#if !defined( DISTI_NO_NOEXCEPT ) && defined( DISTI_HAS_NOEXCEPT )
235/// Macro to wrap the noexcept keyword, removed on compilers that don't support it.
236# define DISTI_FUNC_NOEXCEPT noexcept
237#else
238# undef DISTI_HAS_NOEXCEPT
239/// Macro to wrap the noexcept keyword, removed on compilers that don't support it.
240# define DISTI_FUNC_NOEXCEPT
241#endif
242
243///////////////////////////////////////////////////////////////////////////////////////////////////
244#if !defined( DISTI_NO_SPECIAL_MEM_FUN_DEL ) && defined( DISTI_HAS_SPECIAL_MEM_FUN_DEL )
245/// Macro to wrap function deletion, removed on compilers that don't support it.
246# define DISTI_SPECIAL_MEM_FUN_DELETE = delete
247#else
248# undef DISTI_HAS_SPECIAL_MEM_FUN_DEL
249/// Macro to wrap function deletion, removed on compilers that don't support it.
250# define DISTI_SPECIAL_MEM_FUN_DELETE
251#endif
252
253///////////////////////////////////////////////////////////////////////////////////////////////////
254#if !defined( DISTI_NO_USER_DEFINED_LITERALS ) && defined( DISTI_HAS_USER_DEFINED_LITERALS )
255/// Macro to wrap user defined literals, removed on compilers that don't support them.
256# define DISTI_IF_HAS_USER_DEFINED_LITERAL( x ) x
257#else
258# undef DISTI_HAS_USER_DEFINED_LITERALS
259/// Macro to wrap user defined literals, removed on compilers that don't support them.
260# define DISTI_IF_HAS_USER_DEFINED_LITERAL( x )
261#endif
262
263///////////////////////////////////////////////////////////////////////////////////////////////////
264#if !defined( DISTI_NO_TYPE_TRAITS ) && defined( DISTI_HAS_TYPE_TRAITS )
265/// Use this by including <type_traits> and then providing a default, e.g.,
266/// \code{.cpp}
267/// DISTI_IF_HAS_TYPE_TRAITS_ELSE( std::is_const<T>::value, false )
268/// \endcode
269# define DISTI_IF_HAS_TYPE_TRAITS_ELSE( x, y ) x
270
271////////////////////////////////////////////////////////////////////////////////
272/// Convenience macro to check that one type converts to another at compile-time.
273/// \param T A class to check
274/// \param ConvertsTo A class to test T* against to verify that it can be
275/// converted to ConvertsTo* without a cast.
276////////////////////////////////////////////////////////////////////////////////
277# define DISTI_STATIC_ASSERT_IS_CONVERTIBLE_TO( T, ConvertsTo ) DISTI_STATIC_ASSERT( ( std::is_convertible<T*, ConvertsTo*>::value ), class_does_not_inherit_from_##ConvertsTo );
278
279/// Determines if a class \a T is trivially destructible (i.e., has no side effects)
280# define DISTI_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( std::is_trivially_destructible<T>() )
281/// Macro wrapping std::true_type, removed on compilers that don't support it.
282# define DISTI_TT_TRUE_TYPE std::true_type
283/// Macro wrapping std::false_type, removed on compilers that don't support it.
284# define DISTI_TT_FALSE_TYPE std::false_type
285#else
286# undef DISTI_HAS_TYPE_TRAITS
287/// Use this by including <type_traits> and then providing a default, e.g.,
288/// \code{.cpp}
289/// DISTI_IF_HAS_TYPE_TRAITS_ELSE( std::is_const<T>::value, false )
290/// \endcode
291# define DISTI_IF_HAS_TYPE_TRAITS_ELSE( x, y ) y
292
293# ifndef DOXYGEN_IGNORE
294/// See documentation above
295# define DISTI_STATIC_ASSERT_IS_CONVERTIBLE_TO( T, ConvertsTo ) DISTI_STATIC_ASSERT( ( ::disti::_cppLangSupportDetail::is_convertible<T*, ConvertsTo*>::value ), class_does_not_inherit_from_##ConvertsTo )
296
297/// See documentation above
298# define DISTI_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( ::disti::_cppLangSupportDetail::is_trivially_destructible<T>() )
299# define DISTI_TT_TRUE_TYPE ::disti::_cppLangSupportDetail::true_type
300# define DISTI_TT_FALSE_TYPE ::disti::_cppLangSupportDetail::false_type
301# endif
302
303 namespace disti
304{
305// The _cppLangSupportDetail namespace is here to hide implementation details, mostly for things
306// that are standard but not available on all supported platforms.
307 namespace _cppLangSupportDetail
308{
309 /// Replacement for std::is_convertible, adapted from Loki 0.1.7.
310 /////////////////////////////////////////////////////////////////////////////////
311 /// \copyright The Loki Library, Copyright (c) 2001 by Andrei Alexandrescu<br />
312 /// This code accompanies the book:
313 /// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
314 /// Patterns Applied". Copyright (c) 2001. Addison-Wesley.<br />
315 /// Permission to use, copy, modify, distribute and sell this software for any
316 /// purpose is hereby granted without fee, provided that the above copyright
317 /// notice appear in all copies and that both that copyright notice and this
318 /// permission notice appear in supporting documentation.<br />
319 /// The author or Addison-Welsey Longman make no representations about the
320 /// suitability of this software for any purpose. It is provided "as is"
321 /// without express or implied warranty.<br />
322 /////////////////////////////////////////////////////////////////////////////////
323 template<class T, class U>
324 struct is_convertible
325 {
326 private:
327 typedef char Small;
328 struct Big
329 {
330 char dummy[ 2 ];
331 };
332 static Big Test( ... );
333 static Small Test( U );
334 static T MakeT();
335
336 public:
337 enum
338 {
339 value = sizeof( Small ) == sizeof( ( Test( MakeT() ) ) )
340 };
341 };
342
343 // clang-format off
344 /// Replacement for std::is_convertible, adapted from Loki 0.1.7.
345 template<class T> struct is_convertible<T, T > { enum { value = true }; };
346
347 /// Replacement for std::is_convertible, adapted from Loki 0.1.7.
348 template<class T> struct is_convertible<void, T > { enum { value = false }; };
349
350 /// Replacement for std::is_convertible, adapted from Loki 0.1.7.
351 template<class T> struct is_convertible<T, void> { enum { value = false }; };
352
353 /// Replacement for std::is_convertible, adapted from Loki 0.1.7.
354 template<> struct is_convertible<void, void> { enum { value = true }; };
355
356# if defined( DISTI_USER_DEFINED_IS_TRIVIALLY_DESTRUCTIBLE ) // Prefer the user-defined version if available
357# define DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( DISTI_USER_DEFINED_IS_TRIVIALLY_DESTRUCTIBLE( T ) )
358# else
359 // Use compiler intrinsics for something that cannot be reliably determined without it.
360 // Drawn from Boost 1.55.0's implementation.
361# if defined( _MSC_VER )
362# define DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( __has_trivial_destructor( T ) || ( __is_pod( T ) && __has_trivial_constructor( T ) ) )
363# else
364 // This is defined for all supported versions of GCC and Clang and is also common elsewhere.
365 // Define DISTI_USER_DEFINED_IS_TRIVIALLY_DESTRUCTIBLE() to override.
366# define DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( __has_trivial_destructor( T ) )
367# endif
368# endif
369# if defined( DISTI_USER_DEFINED_IS_DESTRUCTIBLE ) // Prefer the user-defined version if available
370# define DISTI_TT_IS_DESTRUCTIBLE( T ) ( DISTI_USER_DEFINED_IS_DESTRUCTIBLE( T ) )
371# else
372 // This is defined for all supported versions of GCC and Clang and is also common elsewhere.
373 // Define DISTI_USER_DEFINED_IS_DESTRUCTIBLE() to override.
374# define DISTI_TT_IS_DESTRUCTIBLE( T ) ( __is_pod( T ) || __is_class( T ) )
375# endif
376 // clang-format on
377
378# ifndef DOXYGEN_IGNORE
379 template<typename T, T Val>
380 struct integral_constant
381 {
382 static const T value;
383 typedef T value_type;
384 typedef integral_constant<T, Val> type;
385 operator value_type() { return value; }
386 };
387
388 template<typename T, T Val>
389 const T integral_constant<T, Val>::value = Val;
390
391 typedef integral_constant<bool, true> true_type;
392 typedef integral_constant<bool, false> false_type;
393
394 template<typename T>
395 struct is_trivially_destructible
396 : integral_constant<bool, DISTI_TT_IS_DESTRUCTIBLE( T ) && DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T )>
397 {};
398# endif
399
400} // namespace _cppLangSupportDetail
401} // namespace disti
402#endif
403
404///////////////////////////////////////////////////////////////////////////////////////////////////
405#if defined( DISTI_NO_STATIC_ASSERT )
406# undef DISTI_HAS_STATIC_ASSERT
407# define DISTI_STATIC_ASSERT( expr, msg )
408#else
409 /// Inner macro for preprocessor stringification, do not use this macro directly.
410# define DISTI_PREPROC_STRINGIFY_HELPER( s ) # s
411 /// Use this macro to convert a preprocessor define into a literal string.
412# define DISTI_PREPROC_STRINGIFY( s ) DISTI_PREPROC_STRINGIFY_HELPER( s )
413
414# if defined( DISTI_HAS_STATIC_ASSERT )
415 /// \brief Uses C++11's static_assert() because it is available on this platform.
416 /// \param expr a compile-time integral or pointer expression
417 /// \param msg a C identifier that will appear in compiler diagnostics
418 /// \note For older compilers' benefit, \a msg should be a C identifier such as:
419 /// \code{.cpp}
420 /// DISTI_STATIC_ASSERT( (std::is_convertible<T*,ConvertsTo*>::value), class_does_not_inherit_from_##ConvertsTo )
421 /// \endcode
422 /// which shows a compile-time error that typically includes: "ERROR_class_does_not_inherit_from_Group".
423 /// If it is not a C identifier, you may get spurious error messages at compile time compilers without static_assert.
424# define DISTI_STATIC_ASSERT( expr, msg ) static_assert( expr, DISTI_PREPROC_STRINGIFY( msg ) )
425
426/// \brief Uses C++11's static_assert() because it is available on this platform.
427/// \param expr a compile-time integral or pointer expression with a string message.
428/// \param msg a string to help the developer determine what went wrong.
429/// \code{.cpp}
430/// DISTI_STATIC_ASSERT_STR( (std::is_convertible<T*, Base*>::value), "Class does not inherit from Base." );
431/// \endcode
432/// \note Adapted from Loki 0.1.7.
433# define DISTI_STATIC_ASSERT_STR( expr, msg ) static_assert( expr, msg )
434
435# else
436 namespace disti
437{
438 namespace _cppLangSupportDetail
439{
440 // Helpers for DISTI_STATIC_ASSERT
441 // \note Adapted from Loki 0.1.7.
442 template<int>
443 struct CompileTimeError;
444
445 /// Helpers for DISTI_STATIC_ASSERT
446 /// \note Adapted from Loki 0.1.7.
447 template<>
448 struct CompileTimeError<true>
449 {
450 CompileTimeError() {}
451 CompileTimeError( const char* ) {}
452 };
453} // namespace _cppLangSupportDetail
454} // namespace disti
455
456/// \brief Poor man's version of C++11's static_assert()
457/// \param expr a compile-time integral or pointer expression
458/// \param msg a C identifier that will appear in compiler diagnostics
459/// \note For older compilers' benefit, \a msg should be a C identifier such as:
460/// \code{.cpp}
461/// DISTI_STATIC_ASSERT( (std::is_convertible<T*, Base*>::value), class_does_not_inherit_from_Base );
462/// \endcode
463/// which shows a compile-time error that typically includes: "ERROR_class_does_not_inherit_from_Base".
464/// If it is not a C identifier, you may get spurious error messages at compile time compilers without static_assert.
465/// \note Adapted from Loki 0.1.7.
466# define DISTI_STATIC_ASSERT( expr, msg ) \
467 { \
468 ::disti::_cppLangSupportDetail::CompileTimeError<( ( expr ) != 0 )> ERROR_##msg; \
469 (void)ERROR_##msg; \
470 }
471
472/// \param expr a compile-time integral or pointer expression with a string message
473/// \param msg a string to help the developer determine what went wrong.
474/// \code{.cpp}
475/// DISTI_STATIC_ASSERT_STR( (std::is_convertible<T*, Base*>::value), "Class does not inherit from Base." );
476/// \endcode
477/// \note Adapted from Loki 0.1.7.
478# define DISTI_STATIC_ASSERT_STR( expr, msg ) \
479 { \
480 ::disti::_cppLangSupportDetail::CompileTimeError<( ( expr ) != 0 )> ERROR_##__LINE__( msg ); \
481 (void)ERROR_##__LINE__; \
482 }
483# endif
484#endif
485
486/// Defines whether this compiler supports the C++14 deprecated attribute.
487#if defined( DISTI_HAS_DEPRECATED_ATTRIBUTE ) && !defined( DISTI_NO_DEPRECATED_ATTRIBUTE )
488# define DISTI_DEPRECATED( msg ) [[deprecated( msg )]]
489#else
490# define DISTI_DEPRECATED( msg )
491#endif
492
493#include <float.h>
494 namespace disti
495{
496// clang-format off
497/// \details The MaxDigits10 struct. Since not all platforms support C++11, we provide an equivalent feature here that does not require it.
498/// Formulae derived from the proposal for std::numeric_limits<>::max_digits10 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2005.pdf)
499 template<class T> struct MaxDigits10 { static const unsigned long value = 0; /**< The number of digits.*/ };
500/// \see MaxDigits10
501 template<> struct MaxDigits10<float> { static const unsigned long value = 2 + (FLT_MANT_DIG * 30103UL) / 100000UL; /**< The number of digits.*/ };
502/// \see MaxDigits10
503 template<> struct MaxDigits10<double> { static const unsigned long value = 2 + (DBL_MANT_DIG * 30103UL) / 100000UL; /**< The number of digits.*/ };
504/// \see MaxDigits10
505 template<> struct MaxDigits10<long double> { static const unsigned long value = 2 + (LDBL_MANT_DIG * 30103UL) / 100000UL; /**< The number of digits.*/ };
506// clang-format on
507} // namespace disti
508
509#include <cstdlib>
510#include <typeinfo>
511#if defined( __GNUC__ ) || defined( __clang__ )
512# include <cxxabi.h>
513#endif
514 namespace disti
515{
516 template<class T>
517
518/// Transforms C++ ABI identifiers into the original C++ source identifiers
519/// \return String containing transformed C++ source identifier.
520/// \pre none
521/// \post none
522 const char* Demangle()
523{
524#if defined( __GNUC__ ) || defined( __clang__ )
525 static char* s_unmangledName = NULL;
526 std::free( s_unmangledName );
527
528 // https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
529 int status = 0;
530 s_unmangledName = abi::__cxa_demangle( typeid( T ).name(), NULL, NULL, &status );
531
532 if( 0 == status )
533 {
534 return s_unmangledName;
535 }
536#endif
537 return typeid( T ).name();
538}
539} // namespace disti
540
541#endif
disti
Definition: bmpimage.h:47
disti::Demangle
const char * Demangle()
Definition: gls_cpp_lang_support.h:522
disti::MaxDigits10
Definition: gls_cpp_lang_support.h:499
disti::MaxDigits10::value
static const unsigned long value
Definition: gls_cpp_lang_support.h:499