amxmodx/public/amtl/am-cxx.h
2014-12-06 14:00:15 +01:00

214 lines
7.5 KiB
C

// vim: set sts=8 ts=2 sw=2 tw=99 et:
//
// Copyright (C) 2014, David Anderson and AlliedModders LLC
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of AlliedModders LLC nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#ifndef _include_amtl_cxx_support_h_
#define _include_amtl_cxx_support_h_
#if defined(__clang__)
# if !(defined(__clang_major__) && defined(__clang_minor__))
# define KE_CLANG_MAJOR 1
# define KE_CLANG_MINOR __GNUC_MINOR__
# else
# if defined(__apple_build_version__) && clang_major__ > 3
// 4.0 => 3.1, 4.1 => 3.2
# if __clang_major__ == 4
# define KE_CLANG_MAJOR 3
# if __clang_minor__ == 0
# define KE_CLANG_MINOR 1
# else
# define KE_CLANG_MINOR 2
# endif
// 5.0 => 3.3, 5.1 => 3.4
# elif __clang_major__ == 5
# define KE_CLANG_MAJOR 3
# if __clang_minor__ == 0
# define KE_CLANG_MINOR 3
# else
# define KE_CLANG_MINOR 4
# endif
# elif __clang_major__ == 6
# define KE_CLANG_MAJOR 3
# define KE_CLANG_MINOR 5
# endif
# endif
# if !defined(KE_CLANG_MAJOR)
# define KE_CLANG_MAJOR __clang_major__
# endif
# if !defined(KE_CLANG_MINOR)
# define KE_CLANG_MINOR __clang_minor__
# endif
# endif
// Done with horrible clang version detection.
# define KE_CLANG_AT_LEAST(x, y) \
((__clang_major__ > (x)) || (__clang_major__ == x && __clang_minor__ >= y))
# if KE_CLANG_AT_LEAST(2, 9)
# define KE_CXX_HAS_RVAL_REFS 30
# define KE_CXX_HAS_DELETE
# define KE_CXX_HAS_STATIC_ASSERT
# define KE_CXX_HAS_DOUBLE_GT
# define KE_CXX_HAS_ENUM_CLASS
# endif
# if KE_CLANG_AT_LEAST(3, 0)
# define KE_CXX_HAS_OVERRIDE
# define KE_CXX_HAS_EXPLICIT_BOOL
# define KE_CXX_HAS_NULLPTR
# define KE_CXX_HAS_NOEXCEPT
# endif
# if KE_CLANG_AT_LEAST(3, 1)
# define KE_CXX_HAS_CONSTEXPR
# endif
#elif defined(__GNUC__)
# define KE_GCC_AT_LEAST(x, y) ((__GNUC__ > (x)) || (__GNUC__ == x && __GNUC_MINOR__ >= y))
# if KE_GCC_AT_LEAST(4, 3)
# define KE_CXX_HAS_RVAL_REFS 10
# define KE_CXX_HAS_STATIC_ASSERT
# define KE_CXX_HAS_DOUBLE_GT
# endif
# if KE_GCC_AT_LEAST(4, 4)
# define KE_CXX_HAS_DELETE
# define KE_CXX_HAS_ENUM_CLASS
# endif
# if KE_GCC_AT_LEAST(4, 5)
# define KE_CXX_HAS_EXPLICIT_BOOL
# undef KE_CXX_HAS_RVAL_REFS
# define KE_CXX_HAS_RVAL_REFS 21
# endif
# if KE_GCC_AT_LEAST(4, 6)
# define KE_CXX_HAS_NULLPTR
# define KE_CXX_HAS_NOEXCEPT
# define KE_CXX_HAS_CONSTEXPR
# undef KE_CXX_HAS_RVAL_REFS
# define KE_CXX_HAS_RVAL_REFS 30
# endif
# if KE_GCC_AT_LEAST(4, 7)
# define KE_CXX_HAS_OVERRIDE
# endif
#elif defined(_MSC_VER)
# if _MSC_VER >= 1600
# define KE_CXX_HAS_RVAL_REFS 20
# define KE_CXX_HAS_STATIC_ASSERT
# define KE_CXX_HAS_DOUBLE_GT
# define KE_CXX_HAS_NULLPTR
# endif
# if _MSC_VER >= 1700
# undef KE_CXX_HAS_RVAL_REFS
# define KE_CXX_HAS_RVAL_REFS 21
# define KE_CXX_HAS_OVERRIDE
# define KE_CXX_HAS_ENUM_CLASS
# endif
# if _MSC_VER >= 1800
# define KE_CXX_HAS_DELETE
# define KE_CXX_HAS_EXPLICIT_BOOL
# endif
# if _MSC_VER == 1800 && _MSC_FULL_VER == 180021114
# define KE_CXX_HAS_CONSTEXPR
# endif
#else
# error Unrecognized compiler.
#endif
// Done with compiler feature detection.
#if defined(KE_CXX_HAS_OVERRIDE)
# define KE_OVERRIDE override
#else
# define KE_OVERRIDE
#endif
#if defined(KE_CXX_HAS_DELETE)
# define KE_DELETE = delete
#else
# define KE_DELETE
#endif
#if defined(KE_CXX_HAS_NOEXCEPT)
# define KE_NOEXCEPT noexcept
#else
# define KE_NOEXCEPT
#endif
#if defined(KE_CXX_HAS_CONSTEXPR)
# define KE_CONSTEXPR constexpr
#else
# define KE_CONSTEXPR
#endif
#if defined(KE_CXX_HAS_STATIC_ASSERT)
# define KE_STATIC_ASSERT(cond) static_assert(cond, #cond)
#else
# define KE_STATIC_ASSERT(cond) extern int static_assert_f(int a[(cond) ? 1 : -1])
#endif
#if !defined(KE_CXX_HAS_RVAL_REFS) || KE_CXX_HAS_RVAL_REFS < 21
//# error AMTL requires rvalue reference 2.1 support (N2844+)
#endif
#if !defined(KE_CXX_HAS_DOUBLE_GT)
# error AMTL requires support for >> in template names
#endif
#if !defined(KE_CXX_HAS_NULLPTR)
# if defined(__GNUC__) && !defined(__clang__)
# define nullptr __null
# define KE_CXX_HAS_NULLPTR
# else
# error AMTL requires nullptr support
# endif
#endif
#define KE_DEFINE_ENUM_OPERATORS(EnumName) \
static inline EnumName operator |(const EnumName &left, const EnumName &right) { \
return EnumName(uint32_t(left) | uint32_t(right)); \
} \
static inline EnumName operator &(const EnumName &left, const EnumName &right) { \
return EnumName(uint32_t(left) & uint32_t(right)); \
} \
static inline EnumName operator ^(const EnumName &left, const EnumName &right) { \
return EnumName(uint32_t(left) ^ uint32_t(right)); \
} \
static inline EnumName operator ~(const EnumName &flags) { \
return EnumName(~uint32_t(flags)); \
} \
static inline EnumName & operator |=(EnumName &left, const EnumName &right) { \
return left = left | right; \
} \
static inline EnumName & operator &=(EnumName &left, const EnumName &right) { \
return left = left & right; \
} \
static inline EnumName & operator ^=(EnumName &left, const EnumName &right) { \
return left = left ^ right; \
} \
static inline bool operator !(const EnumName &obj) { \
return uint32_t(obj) == 0; \
}
#endif // _include_amtl_cxx_support_h_