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
14reproduced, in whole or part, in any form, or by any means of electronic,
15mechanical, or otherwise, without the written permission of DiSTI. Said
16permission may be derived through the purchase of applicable DiSTI product
17licenses which detail the distribution rights of this content and any
18Derivative Works based on this or other copyrighted DiSTI Software.
19
20 NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26
27 LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34EXCEED FIVE DOLLARS (US$5.00).
35
36 The aforementioned terms and restrictions are governed by the laws of the
37State 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# define DISTI_IF_HAS_CPP11( x )
184# define DISTI_IF_HAS_CPP11_ELSE( x, y ) y
185#endif
186
187///////////////////////////////////////////////////////////////////////////////////////////////////
188// Individual C++11 features. See comment above on DISTI_NO_* vs. DISTI_HAS_* macros.
189///////////////////////////////////////////////////////////////////////////////////////////////////
190#if !defined( DISTI_NO_RVAL_REFS ) && defined( DISTI_HAS_RVAL_REFS )
191# include <utility>
192/// Macro to wrap std::move, removed on compilers that don't support it.
193# define DISTI_RVAL_MOVE( x ) std::move( x )
194/// Macro to wrap std::forward, removed on compilers that don't support it.
195# define DISTI_UREF_FORWARD( T, x ) std::forward<T>( x )
196/// Macro to wrap r-value reference, removed on playforms that don't support it.
197# define DISTI_UREF( T ) T&&
198/// Macro to wrap code that should be excluded if r-value references aren't supported.
199# define DISTI_IF_HAS_RVAL_REFS( x ) x
200/// Macro to wrap code that has two implementations, one for r-value reference support, and the other without.
201# define DISTI_IF_HAS_RVAL_REFS_ELSE( x, y ) x
202#else
203# undef DISTI_HAS_RVAL_REFS
204# define DISTI_RVAL_MOVE( x ) x
205# define DISTI_UREF_FORWARD( T, x ) x
206# define DISTI_UREF( T ) const T&
207# define DISTI_IF_HAS_RVAL_REFS( x )
208# define DISTI_IF_HAS_RVAL_REFS_ELSE( x, y ) y
209#endif
210
211///////////////////////////////////////////////////////////////////////////////////////////////////
212#if !defined( DISTI_NO_METHOD_OVERRIDE ) && defined( DISTI_HAS_METHOD_OVERRIDE )
213/// Macro to wrap the override keyword, removed on compilers that don't support it.
214# define DISTI_METHOD_OVERRIDE override
215/// Macro to wrap the final keyword, removed on compilers that don't support it.
216# define DISTI_FINAL final
217#else
218# undef DISTI_HAS_METHOD_OVERRIDE
219# define DISTI_METHOD_OVERRIDE
220# define DISTI_FINAL
221#endif
222
223///////////////////////////////////////////////////////////////////////////////////////////////////
224#if !defined( DISTI_NO_NOEXCEPT ) && defined( DISTI_HAS_NOEXCEPT )
225# define DISTI_FUNC_NOEXCEPT noexcept
226#else
227# undef DISTI_HAS_NOEXCEPT
228/// Macro to wrap the noexcept keyword, removed on compilers that don't support it.
229# define DISTI_FUNC_NOEXCEPT
230#endif
231
232///////////////////////////////////////////////////////////////////////////////////////////////////
233#if !defined( DISTI_NO_SPECIAL_MEM_FUN_DEL ) && defined( DISTI_HAS_SPECIAL_MEM_FUN_DEL )
234/// Macro to wrap function deletion, removed on compilers that don't support it.
235# define DISTI_SPECIAL_MEM_FUN_DELETE = delete
236#else
237# undef DISTI_HAS_SPECIAL_MEM_FUN_DEL
238# define DISTI_SPECIAL_MEM_FUN_DELETE
239#endif
240
241///////////////////////////////////////////////////////////////////////////////////////////////////
242#if !defined( DISTI_NO_USER_DEFINED_LITERALS ) && defined( DISTI_HAS_USER_DEFINED_LITERALS )
243# define DISTI_IF_HAS_USER_DEFINED_LITERAL( x ) x
244#else
245# undef DISTI_HAS_USER_DEFINED_LITERALS
246/// Macro to wrap user defined literals, removed on compilers that don't support them.
247# define DISTI_IF_HAS_USER_DEFINED_LITERAL( x )
248#endif
249
250///////////////////////////////////////////////////////////////////////////////////////////////////
251#if !defined( DISTI_NO_TYPE_TRAITS ) && defined( DISTI_HAS_TYPE_TRAITS )
252/// Use this by including <type_traits> and then providing a default, e.g.,
253/// \code{.cpp}
254/// DISTI_IF_HAS_TYPE_TRAITS_ELSE( std::is_const<T>::value, false )
255/// \endcode
256# define DISTI_IF_HAS_TYPE_TRAITS_ELSE( x, y ) x
257
258////////////////////////////////////////////////////////////////////////////////
259/// Convenience macro to check that one type converts to another at compile-time.
260/// \param T A class to check
261/// \param ConvertsTo A class to test T* against to verify that it can be
262/// converted to ConvertsTo* without a cast.
263////////////////////////////////////////////////////////////////////////////////
264# define DISTI_STATIC_ASSERT_IS_CONVERTIBLE_TO( T, ConvertsTo ) DISTI_STATIC_ASSERT( ( std::is_convertible<T*, ConvertsTo*>::value ), class_does_not_inherit_from_##ConvertsTo );
265
266/// Determines if a class \a T is trivially destructible (i.e., has no side effects)
267# define DISTI_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( std::is_trivially_destructible<T>() )
268/// Macro wrapping std::true_type, removed on compilers that don't support it.
269# define DISTI_TT_TRUE_TYPE std::true_type
270/// Macro wrapping std::false_type, removed on compilers that don't support it.
271# define DISTI_TT_FALSE_TYPE std::false_type
272#else
273# undef DISTI_HAS_TYPE_TRAITS
274# define DISTI_IF_HAS_TYPE_TRAITS_ELSE( x, y ) y
275
276// See documentation above
277# 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 )
278
279// See documentation above
280# define DISTI_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( ::disti::_cppLangSupportDetail::is_trivially_destructible<T>() )
281# define DISTI_TT_TRUE_TYPE ::disti::_cppLangSupportDetail::true_type
282# define DISTI_TT_FALSE_TYPE ::disti::_cppLangSupportDetail::false_type
283
284namespace disti
285{
286// The _cppLangSupportDetail namespace is here to hide implementation details, mostly for things
287// that are standard but not available on all supported platforms.
288namespace _cppLangSupportDetail
289{
290 /// Replacement for std::is_convertible, adapted from Loki 0.1.7.
291 /////////////////////////////////////////////////////////////////////////////////
292 /// \copyright The Loki Library, Copyright (c) 2001 by Andrei Alexandrescu<br />
293 /// This code accompanies the book:
294 /// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
295 /// Patterns Applied". Copyright (c) 2001. Addison-Wesley.<br />
296 /// Permission to use, copy, modify, distribute and sell this software for any
297 /// purpose is hereby granted without fee, provided that the above copyright
298 /// notice appear in all copies and that both that copyright notice and this
299 /// permission notice appear in supporting documentation.<br />
300 /// The author or Addison-Welsey Longman make no representations about the
301 /// suitability of this software for any purpose. It is provided "as is"
302 /// without express or implied warranty.<br />
303 /////////////////////////////////////////////////////////////////////////////////
304 template<class T, class U>
305 struct is_convertible
306 {
307 private:
308 typedef char Small;
309 struct Big
310 {
311 char dummy[ 2 ];
312 };
313 static Big Test( ... );
314 static Small Test( U );
315 static T MakeT();
316
317 public:
318 enum
319 {
320 value = sizeof( Small ) == sizeof( ( Test( MakeT() ) ) )
321 };
322 };
323
324 // clang-format off
325 template<class T> struct is_convertible<T, T > { enum { value = true }; }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
326 template<class T> struct is_convertible<void, T > { enum { value = false }; }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
327 template<class T> struct is_convertible<T, void> { enum { value = false }; }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
328 template<> struct is_convertible<void, void> { enum { value = true }; }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
329
330# if defined( DISTI_USER_DEFINED_IS_TRIVIALLY_DESTRUCTIBLE ) // Prefer the user-defined version if available
331# define DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( DISTI_USER_DEFINED_IS_TRIVIALLY_DESTRUCTIBLE( T ) )
332# else
333 // Use compiler intrinsics for something that cannot be reliably determined without it.
334 // Drawn from Boost 1.55.0's implementation.
335# if defined( _MSC_VER )
336# define DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( __has_trivial_destructor( T ) || ( __is_pod( T ) && __has_trivial_constructor( T ) ) )
337# else
338 // This is defined for all supported versions of GCC and Clang and is also common elsewhere.
339 // Define DISTI_USER_DEFINED_IS_TRIVIALLY_DESTRUCTIBLE() to override.
340# define DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T ) ( __has_trivial_destructor( T ) )
341# endif
342# endif
343# if defined( DISTI_USER_DEFINED_IS_DESTRUCTIBLE ) // Prefer the user-defined version if available
344# define DISTI_TT_IS_DESTRUCTIBLE( T ) ( DISTI_USER_DEFINED_IS_DESTRUCTIBLE( T ) )
345# else
346 // This is defined for all supported versions of GCC and Clang and is also common elsewhere.
347 // Define DISTI_USER_DEFINED_IS_DESTRUCTIBLE() to override.
348# define DISTI_TT_IS_DESTRUCTIBLE( T ) ( __is_pod( T ) || __is_class( T ) )
349# endif
350 // clang-format on
351
352 template<typename T, T Val>
353 struct integral_constant
354 {
355 static const T value;
356 typedef T value_type;
357 typedef integral_constant<T, Val> type;
358 operator value_type() { return value; }
359 };
360
361 template<typename T, T Val>
362 const T integral_constant<T, Val>::value = Val;
363
364 typedef integral_constant<bool, true> true_type;
365 typedef integral_constant<bool, false> false_type;
366
367 template<typename T>
368 struct is_trivially_destructible
369 : integral_constant<bool, DISTI_TT_IS_DESTRUCTIBLE( T ) && DISTI_TT_IS_TRIVIALLY_DESTRUCTIBLE( T )>
370 {};
371
372} // namespace _cppLangSupportDetail
373} // namespace disti
374#endif
375
376///////////////////////////////////////////////////////////////////////////////////////////////////
377#if defined( DISTI_NO_STATIC_ASSERT )
378# undef DISTI_HAS_STATIC_ASSERT
379# define DISTI_STATIC_ASSERT( expr, msg )
380#else
381 /// Inner macro for preprocessor stringification, do not use this macro directly.
382# define DISTI_PREPROC_STRINGIFY_HELPER( s ) # s
383 /// Use this macro to convert a preprocessor define into a literal string.
384# define DISTI_PREPROC_STRINGIFY( s ) DISTI_PREPROC_STRINGIFY_HELPER( s )
385
386# if defined( DISTI_HAS_STATIC_ASSERT )
387 /// \brief Uses C++11's static_assert() because it is available on this platform.
388 /// \param expr a compile-time integral or pointer expression
389 /// \param msg a C identifier that will appear in compiler diagnostics
390 /// \note For older compilers' benefit, \a msg should be a C identifier such as:
391 /// \code{.cpp}
392 /// DISTI_STATIC_ASSERT( (std::is_convertible<T*,ConvertsTo*>::value), class_does_not_inherit_from_##ConvertsTo )
393 /// \endcode
394 /// which shows a compile-time error that typically includes: "ERROR_class_does_not_inherit_from_Group".
395 /// If it is not a C identifier, you may get spurious error messages at compile time compilers without static_assert.
396# define DISTI_STATIC_ASSERT( expr, msg ) static_assert( expr, DISTI_PREPROC_STRINGIFY( msg ) )
397
398/// \brief Uses C++11's static_assert() because it is available on this platform.
399/// \param expr a compile-time integral or pointer expression with a string message.
400/// \param msg a string to help the developer determine what went wrong.
401/// \code{.cpp}
402/// DISTI_STATIC_ASSERT_STR( (std::is_convertible<T*, Base*>::value), "Class does not inherit from Base." );
403/// \endcode
404/// \note Adapted from Loki 0.1.7.
405# define DISTI_STATIC_ASSERT_STR( expr, msg ) static_assert( expr, msg )
406
407# else
408namespace disti
409{
410namespace _cppLangSupportDetail
411{
412 // Helpers for DISTI_STATIC_ASSERT
413 // \note Adapted from Loki 0.1.7.
414 template<int>
415 struct CompileTimeError;
416 template<>
417 struct CompileTimeError<true>
418 {
419 CompileTimeError() {}
420 CompileTimeError( const char* ) {}
421 };
422} // namespace _cppLangSupportDetail
423} // namespace disti
424
425/// \brief Poor man's version of C++11's static_assert()
426/// \param expr a compile-time integral or pointer expression
427/// \param msg a C identifier that will appear in compiler diagnostics
428/// \note For older compilers' benefit, \a msg should be a C identifier such as:
429/// \code{.cpp}
430/// DISTI_STATIC_ASSERT( (std::is_convertible<T*, Base*>::value), class_does_not_inherit_from_Base );
431/// \endcode
432/// which shows a compile-time error that typically includes: "ERROR_class_does_not_inherit_from_Base".
433/// If it is not a C identifier, you may get spurious error messages at compile time compilers without static_assert.
434/// \note Adapted from Loki 0.1.7.
435# define DISTI_STATIC_ASSERT( expr, msg ) \
436 { \
437 ::disti::_cppLangSupportDetail::CompileTimeError<( ( expr ) != 0 )> ERROR_##msg; \
438 (void)ERROR_##msg; \
439 }
440
441/// \param expr a compile-time integral or pointer expression with a string message
442/// \param msg a string to help the developer determine what went wrong.
443/// \code{.cpp}
444/// DISTI_STATIC_ASSERT_STR( (std::is_convertible<T*, Base*>::value), "Class does not inherit from Base." );
445/// \endcode
446/// \note Adapted from Loki 0.1.7.
447# define DISTI_STATIC_ASSERT_STR( expr, msg ) \
448 { \
449 ::disti::_cppLangSupportDetail::CompileTimeError<( ( expr ) != 0 )> ERROR_##__LINE__( msg ); \
450 (void)ERROR_##__LINE__; \
451 }
452# endif
453#endif
454
455/// Defines whether this compiler supports the C++14 deprecated attribute.
456#if defined( DISTI_HAS_DEPRECATED_ATTRIBUTE ) && !defined( DISTI_NO_DEPRECATED_ATTRIBUTE )
457# define DISTI_DEPRECATED( msg ) [[deprecated( msg )]]
458#else
459# define DISTI_DEPRECATED( msg )
460#endif
461
462#include <float.h>
463namespace disti
464{
465// clang-format off
466/// \details The MaxDigits10 struct. Since not all platforms support C++11, we provide an equivalent feature here that does not require it.
467/// Formulae derived from the proposal for std::numeric_limits<>::max_digits10 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2005.pdf)
468template<class T> struct MaxDigits10 { static const unsigned long value = 0; /**< The number of digits.*/ };
469/// \see MaxDigits10
470template<> struct MaxDigits10<float> { static const unsigned long value = 2 + (FLT_MANT_DIG * 30103UL) / 100000UL; /**< The number of digits.*/ };
471/// \see MaxDigits10
472template<> struct MaxDigits10<double> { static const unsigned long value = 2 + (DBL_MANT_DIG * 30103UL) / 100000UL; /**< The number of digits.*/ };
473/// \see MaxDigits10
474template<> struct MaxDigits10<long double> { static const unsigned long value = 2 + (LDBL_MANT_DIG * 30103UL) / 100000UL; /**< The number of digits.*/ };
475// clang-format on
476} // namespace disti
477
478#endif
Force inclusion of the DirectShow library.
Definition: bmpimage.h:47
Definition: gls_cpp_lang_support.h:468
static const unsigned long value
Definition: gls_cpp_lang_support.h:468