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 support
44 //
45 // We use a subset of C++11 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_SPECIAL_MEM_FUN_DEL // For "= delete"
54 // DISTI_HAS_TYPE_TRAITS // For compile-time checking via type-traits
55 // DISTI_HAS_STATIC_ASSERT // For static_assert support
56 //
57 // If our detection is incorrect, override it with a corresponding "NO" define:
58 //
59 // DISTI_NO_RVAL_REFS // For rvalue references
60 // DISTI_NO_METHOD_OVERRIDE // For "override" and "final" keywords
61 // DISTI_NO_METHOD_FINAL // For "final" keyword
62 // DISTI_NO_SPECIAL_MEM_FUN_DEL // For "= delete"
63 // DISTI_NO_TYPE_TRAITS // For compile-time checking via type-traits
64 // DISTI_NO_STATIC_ASSERT // For static_assert support
65 
66 /////////////////////////////////////////////////////////////////////////////////////
67 // Microsoft C++ Compiler -- https://msdn.microsoft.com/en-us/library/hh567368.aspx
68 /////////////////////////////////////////////////////////////////////////////////////
69 #if defined( _MSC_VER )
70 # if _MSC_VER >= 1700 // >= VS2012
71 # define DISTI_HAS_RVAL_REFS
72 # define DISTI_HAS_METHOD_OVERRIDE
73 # define DISTI_HAS_TYPE_TRAITS
74 # define DISTI_HAS_STATIC_ASSERT
75 # endif
76 # if _MSC_VER >= 1800 // >= VS2013
77 # define DISTI_HAS_SPECIAL_MEM_FUN_DEL
78 # endif
79 ////////////////////////////////////////////////////////////////////////////////
80 // GCC versions -- https://gcc.gnu.org/projects/cxx-status.html#cxx11
81 ////////////////////////////////////////////////////////////////////////////////
82 #elif defined( __GNUC__ )
83  // __cpp_rvalue_references doesn't seem to be defined in GCC, despite the documentation, so we have an alternative check also
84 # if __cpp_rvalue_references >= 200610 || ( ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 ) ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L ) )
85 # define DISTI_HAS_RVAL_REFS
86 # endif
87 # if __cpp_static_assert >= 200410 && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L )
88 # define DISTI_HAS_STATIC_ASSERT
89 # endif
90 # if( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 7 ) ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L )
91 # define DISTI_HAS_METHOD_OVERRIDE
92 
93  // This actually depends on which standard library is in use, but it's a safe bet.
94 # define DISTI_HAS_TYPE_TRAITS
95 # endif
96 # if( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || __cplusplus >= 201103L )
97 # define DISTI_HAS_SPECIAL_MEM_FUN_DEL
98 # endif
99 ////////////////////////////////////////////////////////////////////////////////
100 // Clang versions -- http://clang.llvm.org/cxx_status.html
101 ////////////////////////////////////////////////////////////////////////////////
102 #elif defined( __clang__ )
103 # if __has_feature( cxx_rvalue_references )
104 # define DISTI_HAS_RVAL_REFS
105 # endif
106 # if __has_feature( cxx_override_control )
107 # define DISTI_HAS_METHOD_OVERRIDE
108 # endif
109 # if __has_feature( cxx_defaulted_functions ) && __has_feature( cxx_deleted_functions )
110 # define DISTI_HAS_SPECIAL_MEM_FUN_DEL
111 # endif
112 # if __has_feature( cxx_static_assert )
113 # define DISTI_HAS_STATIC_ASSERT
114 # endif
115 
116  // This actually depends on which standard library is in use, but it's a safe bet.
117 # define DISTI_HAS_TYPE_TRAITS
118 #endif
119 
120 ///////////////////////////////////////////////////////////////////////////////////////////////////
121 // Shortcut for unrecognized compilers
122 ///////////////////////////////////////////////////////////////////////////////////////////////////
123 #ifdef DISTI_HAS_CPP11 // A single switch to enable everything since compiler is highly compliant
124  // These macros can help with cross-platform portability
125 # define DISTI_IF_HAS_CPP11( x ) x
126 # define DISTI_IF_HAS_CPP11_ELSE( x, y ) x
127 
128 # define DISTI_HAS_RVAL_REFS
129 # define DISTI_HAS_METHOD_OVERRIDE
130 # define DISTI_HAS_SPECIAL_MEM_FUN_DEL
131 # define DISTI_HAS_TYPE_TRAITS
132 # define DISTI_HAS_STATIC_ASSERT
133 #else // Not fully C++11; some features may be enabled piecemeal
134  // These macros can help with cross-platform portability
135 # define DISTI_IF_HAS_CPP11( x )
136 # define DISTI_IF_HAS_CPP11_ELSE( x, y ) y
137 #endif
138 
139 ///////////////////////////////////////////////////////////////////////////////////////////////////
140 // Individual C++11 features. See comment above on DISTI_NO_* vs. DISTI_HAS_* macros.
141 ///////////////////////////////////////////////////////////////////////////////////////////////////
142 #if !defined( DISTI_NO_RVAL_REFS ) && defined( DISTI_HAS_RVAL_REFS )
143 # include <utility>
144 # define DISTI_RVAL_MOVE( x ) std::move( x )
145 # define DISTI_IF_HAS_RVAL_REFS_ELSE( x, y ) x
146 #else
147 # undef DISTI_HAS_RVAL_REFS
148 # define DISTI_RVAL_MOVE( x ) ( x )
149 # define DISTI_IF_HAS_RVAL_REFS_ELSE( x, y ) y
150 #endif
151 
152 ///////////////////////////////////////////////////////////////////////////////////////////////////
153 #if !defined( DISTI_NO_METHOD_OVERRIDE ) && defined( DISTI_HAS_METHOD_OVERRIDE )
154  // Add this to the end of an overridden method
155 # define DISTI_METHOD_OVERRIDE override
156  // Add this to the end of a method that should not be overridden
157 # define DISTI_METHOD_FINAL final
158 #else
159 # undef DISTI_HAS_METHOD_OVERRIDE
160 # define DISTI_METHOD_OVERRIDE
161 # define DISTI_METHOD_FINAL
162 #endif
163 
164 ///////////////////////////////////////////////////////////////////////////////////////////////////
165 #if !defined( DISTI_NO_SPECIAL_MEM_FUN_DEL ) && defined( DISTI_HAS_SPECIAL_MEM_FUN_DEL )
166  // Add these to the end of special member functions to delete them.
167 # define DISTI_SPECIAL_MEM_FUN_DELETE = delete
168 #else
169 # undef DISTI_HAS_SPECIAL_MEM_FUN_DEL
170 # define DISTI_SPECIAL_MEM_FUN_DELETE
171 #endif
172 
173 ///////////////////////////////////////////////////////////////////////////////////////////////////
174 #if !defined( DISTI_NO_TYPE_TRAITS ) && defined( DISTI_HAS_TYPE_TRAITS )
175  // Use this by including <type_traits> and then providing a default, e.g.,
176  // DISTI_IF_HAS_TYPE_TRAITS_ELSE( std::is_const<T>::value, false )
177 # define DISTI_IF_HAS_TYPE_TRAITS_ELSE( x, y ) x
178 #else
179 # undef DISTI_HAS_TYPE_TRAITS
180 # define DISTI_IF_HAS_TYPE_TRAITS_ELSE( x, y ) y
181 
182 namespace disti
183 {
184 // The _cppLangSupportDetail namespace is here to hide implementation details, mostly for things
185 // that are standard but not available on all supported platforms.
186 namespace _cppLangSupportDetail
187 {
188  /// Replacement for std::is_convertible, adapted from Loki 0.1.7.
189  /////////////////////////////////////////////////////////////////////////////////
190  /// \copyright The Loki Library, Copyright (c) 2001 by Andrei Alexandrescu<br />
191  /// This code accompanies the book:
192  /// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
193  /// Patterns Applied". Copyright (c) 2001. Addison-Wesley.<br />
194  /// Permission to use, copy, modify, distribute and sell this software for any
195  /// purpose is hereby granted without fee, provided that the above copyright
196  /// notice appear in all copies and that both that copyright notice and this
197  /// permission notice appear in supporting documentation.<br />
198  /// The author or Addison-Welsey Longman make no representations about the
199  /// suitability of this software for any purpose. It is provided "as is"
200  /// without express or implied warranty.<br />
201  /////////////////////////////////////////////////////////////////////////////////
202  template<class T, class U>
204  {
205  private:
206  typedef char Small;
207  struct Big
208  {
209  char dummy[ 2 ];
210  };
211  static Big Test( ... );
212  static Small Test( U );
213  static T MakeT();
214 
215  public:
216  enum
217  {
218  value = sizeof( Small ) == sizeof( ( Test( MakeT() ) ) )
219  };
220  };
221 
222  template<class T>
223  struct is_convertible<T, T>
224  {
225  enum
226  {
227  value = true
228  };
229  }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
230  template<class T>
231  struct is_convertible<void, T>
232  {
233  enum
234  {
235  value = false
236  };
237  }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
238  template<class T>
239  struct is_convertible<T, void>
240  {
241  enum
242  {
243  value = false
244  };
245  }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
246  template<>
247  struct is_convertible<void, void>
248  {
249  enum
250  {
251  value = true
252  };
253  }; //< Replacement for std::is_convertible, adapted from Loki 0.1.7.
254 } // namespace _cppLangSupportDetail
255 } // namespace disti
256 #endif
257 
258 ///////////////////////////////////////////////////////////////////////////////////////////////////
259 #if defined( DISTI_NO_STATIC_ASSERT )
260 # undef DISTI_HAS_STATIC_ASSERT
261 # define DISTI_STATIC_ASSERT( expr, msg )
262 #else
263 # define DISTI_PREPROC_STRINGIFY_HELPER( s ) # s
264 # define DISTI_PREPROC_STRINGIFY( s ) DISTI_PREPROC_STRINGIFY_HELPER( s )
265 
266 # if defined( DISTI_HAS_STATIC_ASSERT )
267  /// \brief Uses C++11's static_assert() because it is available on this platform.
268  /// \param expr a compile-time integral or pointer expression
269  /// \param msg a C identifier that will appear in compiler diagnostics
270  /// \note For older compilers' benefit, \a msg should be a C identifier such as:
271  /// \code{.cpp}
272  /// DISTI_STATIC_ASSERT( (std::is_convertible<T*,ConvertsTo*>::value), class_does_not_inherit_from_##ConvertsTo )
273  /// \endcode
274  /// which shows a compile-time error that typically includes: "ERROR_class_does_not_inherit_from_Group".
275  /// If it is not a C identifier, you may get spurious error messages at compile time compilers without static_assert.
276 # define DISTI_STATIC_ASSERT( expr, msg ) static_assert( expr, DISTI_PREPROC_STRINGIFY( msg ) )
277 # else
278 namespace disti
279 {
280 namespace _cppLangSupportDetail
281 {
282  // Helpers for DISTI_STATIC_ASSERT
283  // \note Adapted from Loki 0.1.7.
284  template<int>
286  template<>
287  struct CompileTimeError<true>
288  {
289  CompileTimeError() {}
290  };
291 } // namespace _cppLangSupportDetail
292 } // namespace disti
293 
294 /// \brief Poor man's version of C++11's static_assert()
295 /// \param expr a compile-time integral or pointer expression
296 /// \param msg a C identifier that will appear in compiler diagnostics
297 /// \note For older compilers' benefit, \a msg should be a C identifier such as:
298 /// \code{.cpp}
299 /// DISTI_STATIC_ASSERT( (std::is_convertible<T*,ConvertsTo*>::value), class_does_not_inherit_from_##ConvertsTo )
300 /// \endcode
301 /// which shows a compile-time error that typically includes: "ERROR_class_does_not_inherit_from_Group".
302 /// If it is not a C identifier, you may get spurious error messages at compile time compilers without static_assert.
303 /// \note Adapted from Loki 0.1.7.
304 # define DISTI_STATIC_ASSERT( expr, msg ) \
305  { \
306  ::disti::_cppLangSupportDetail::CompileTimeError<( ( expr ) != 0 )> ERROR_##msg; \
307  (void)ERROR_##msg; \
308  }
309 # endif
310 #endif
311 
312 ////////////////////////////////////////////////////////////////////////////////
313 /// Convenience macro to check that one type converts to another at compile-time.
314 /// \param T A class to check
315 /// \param ConvertsTo A class to test T* against to verify that it can be
316 /// converted to ConvertsTo* without a cast.
317 /// \note This macro appears here for grouping with like code, but macros
318 /// aren't scoped to namespace.
319 ////////////////////////////////////////////////////////////////////////////////
320 #ifdef DISTI_HAS_TYPE_TRAITS
321 # define DISTI_STATIC_ASSERT_IS_CONVERTIBLE_TO( T, ConvertsTo ) DISTI_STATIC_ASSERT( ( std::is_convertible<T*, ConvertsTo*>::value ), class_does_not_inherit_from_##ConvertsTo );
322 #else
323 # 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 )
324 #endif
325 
326 #endif
Replacement for std::is_convertible, adapted from Loki 0.1.7.
Definition: gls_cpp_lang_support.h:203
Definition: gls_cpp_lang_support.h:285
Definition: bmpimage.h:46