#if !defined(spp_config_h_guard)
#define spp_config_h_guard

// --------------------------------------------------
// Sparsepp config macros
// some can be overridden on the command line
// --------------------------------------------------
#ifndef SPP_NAMESPACE
#define SPP_NAMESPACE spp
#endif

#ifndef spp_
#define spp_ SPP_NAMESPACE
#endif

#ifndef SPP_DEFAULT_ALLOCATOR
#if (defined(SPP_USE_SPP_ALLOC) && SPP_USE_SPP_ALLOC) && defined(_MSC_VER)
// -----------------------------------------------------------------------------
// When building with the Microsoft compiler, we use a custom allocator because
// the default one fragments memory when reallocating. This is desirable only
// when creating large sparsepp hash maps. If you create lots of small
// hash_maps, define the following before including spp.h:
//     #define SPP_DEFAULT_ALLOCATOR spp::libc_allocator
// -----------------------------------------------------------------------------
#define SPP_DEFAULT_ALLOCATOR spp_::spp_allocator
#define SPP_INCLUDE_SPP_ALLOC
#else
#define SPP_DEFAULT_ALLOCATOR spp_::libc_allocator
#endif
#endif

#ifndef SPP_GROUP_SIZE
// must be 32 or 64
#define SPP_GROUP_SIZE 32
#endif

#ifndef SPP_ALLOC_SZ
// must be power of 2 (0 = aggressive alloc, 1 = smallest memory usage, 2 = good
// compromise)
#define SPP_ALLOC_SZ 0
#endif

#ifndef SPP_STORE_NUM_ITEMS
// 1 uses a little bit more memory, but faster!!
#define SPP_STORE_NUM_ITEMS 1
#endif

// ---------------------------------------------------------------------------
// Compiler detection code (SPP_ preprocessor macros) derived from Boost
// libraries. Therefore Boost software licence reproduced below.
// ---------------------------------------------------------------------------
// Boost Software License - Version 1.0 - August 17th, 2003
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// ---------------------------------------------------------------------------

// Boost like configuration
// ------------------------
#if defined __clang__

#if defined(i386)
#include <cpuid.h>
inline void spp_cpuid(int info[4], int InfoType) {
  __cpuid_count(InfoType, 0, info[0], info[1], info[2], info[3]);
}
#endif

#define SPP_POPCNT __builtin_popcount
#define SPP_POPCNT64 __builtin_popcountll

#define SPP_HAS_CSTDINT

#ifndef __has_extension
#define __has_extension __has_feature
#endif

#if !__has_feature(cxx_exceptions) && !defined(SPP_NO_EXCEPTIONS)
#define SPP_NO_EXCEPTIONS
#endif

#if !__has_feature(cxx_rtti) && !defined(SPP_NO_RTTI)
#define SPP_NO_RTTI
#endif

#if !__has_feature(cxx_rtti) && !defined(SPP_NO_TYPEID)
#define SPP_NO_TYPEID
#endif

#if defined(__int64) && !defined(__GNUC__)
#define SPP_HAS_MS_INT64
#endif

#define SPP_HAS_NRVO

// Branch prediction hints
#if defined(__has_builtin)
#if __has_builtin(__builtin_expect)
#define SPP_LIKELY(x) __builtin_expect(x, 1)
#define SPP_UNLIKELY(x) __builtin_expect(x, 0)
#endif
#endif

// Clang supports "long long" in all compilation modes.
#define SPP_HAS_LONG_LONG

#if !__has_feature(cxx_constexpr)
#define SPP_NO_CXX11_CONSTEXPR
#endif

#if !__has_feature(cxx_decltype)
#define SPP_NO_CXX11_DECLTYPE
#endif

#if !__has_feature(cxx_decltype_incomplete_return_types)
#define SPP_NO_CXX11_DECLTYPE_N3276
#endif

#if !__has_feature(cxx_defaulted_functions)
#define SPP_NO_CXX11_DEFAULTED_FUNCTIONS
#endif

#if !__has_feature(cxx_deleted_functions)
#define SPP_NO_CXX11_DELETED_FUNCTIONS
#endif

#if !__has_feature(cxx_explicit_conversions)
#define SPP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#endif

#if !__has_feature(cxx_default_function_template_args)
#define SPP_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
#endif

#if !__has_feature(cxx_generalized_initializers)
#define SPP_NO_CXX11_HDR_INITIALIZER_LIST
#endif

#if !__has_feature(cxx_lambdas)
#define SPP_NO_CXX11_LAMBDAS
#endif

#if !__has_feature(cxx_local_type_template_args)
#define SPP_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
#endif

#if !__has_feature(cxx_raw_string_literals)
#define SPP_NO_CXX11_RAW_LITERALS
#endif

#if !__has_feature(cxx_reference_qualified_functions)
#define SPP_NO_CXX11_REF_QUALIFIERS
#endif

#if !__has_feature(cxx_generalized_initializers)
#define SPP_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
#endif

#if !__has_feature(cxx_rvalue_references)
#define SPP_NO_CXX11_RVALUE_REFERENCES
#endif

#if !__has_feature(cxx_static_assert)
#define SPP_NO_CXX11_STATIC_ASSERT
#endif

#if !__has_feature(cxx_alias_templates)
#define SPP_NO_CXX11_TEMPLATE_ALIASES
#endif

#if !__has_feature(cxx_variadic_templates)
#define SPP_NO_CXX11_VARIADIC_TEMPLATES
#endif

#if !__has_feature(cxx_user_literals)
#define SPP_NO_CXX11_USER_DEFINED_LITERALS
#endif

#if !__has_feature(cxx_alignas)
#define SPP_NO_CXX11_ALIGNAS
#endif

#if !__has_feature(cxx_trailing_return)
#define SPP_NO_CXX11_TRAILING_RESULT_TYPES
#endif

#if !__has_feature(cxx_inline_namespaces)
#define SPP_NO_CXX11_INLINE_NAMESPACES
#endif

#if !__has_feature(cxx_override_control)
#define SPP_NO_CXX11_FINAL
#endif

#if !(__has_feature(__cxx_binary_literals__) || \
      __has_extension(__cxx_binary_literals__))
#define SPP_NO_CXX14_BINARY_LITERALS
#endif

#if !__has_feature(__cxx_decltype_auto__)
#define SPP_NO_CXX14_DECLTYPE_AUTO
#endif

#if !__has_feature(__cxx_init_captures__)
#define SPP_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
#endif

#if !__has_feature(__cxx_generic_lambdas__)
#define SPP_NO_CXX14_GENERIC_LAMBDAS
#endif

#if !__has_feature(__cxx_generic_lambdas__) || \
    !__has_feature(__cxx_relaxed_constexpr__)
#define SPP_NO_CXX14_CONSTEXPR
#endif

#if !__has_feature(__cxx_return_type_deduction__)
#define SPP_NO_CXX14_RETURN_TYPE_DEDUCTION
#endif

#if !__has_feature(__cxx_variable_templates__)
#define SPP_NO_CXX14_VARIABLE_TEMPLATES
#endif

#if __cplusplus < 201400
#define SPP_NO_CXX14_DIGIT_SEPARATORS
#endif

#if defined(__has_builtin) && __has_builtin(__builtin_unreachable)
#define SPP_UNREACHABLE_RETURN(x) __builtin_unreachable();
#endif

#define SPP_ATTRIBUTE_UNUSED __attribute__((__unused__))

#ifndef SPP_COMPILER
#define SPP_COMPILER "Clang version " __clang_version__
#endif

#define SPP_CLANG 1

#elif defined __GNUC__

#define SPP_GCC_VERSION \
  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)

//  definition to expand macro then apply to pragma message
// #define VALUE_TO_STRING(x) #x
// #define VALUE(x) VALUE_TO_STRING(x)
// #define VAR_NAME_VALUE(var) #var "="  VALUE(var)
// #pragma message(VAR_NAME_VALUE(SPP_GCC_VERSION))

#if defined(i386)
#include <cpuid.h>
inline void spp_cpuid(int info[4], int InfoType) {
  __cpuid_count(InfoType, 0, info[0], info[1], info[2], info[3]);
}
#endif

// __POPCNT__ defined when the compiled with popcount support
// (-mpopcnt compiler option is given for example)
#ifdef __POPCNT__
// slower unless compiled with -mpopcnt
#define SPP_POPCNT __builtin_popcount
#define SPP_POPCNT64 __builtin_popcountll
#endif

#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
#define SPP_GCC_CXX11
#endif

#if __GNUC__ == 3
#if defined(__PATHSCALE__)
#define SPP_NO_TWO_PHASE_NAME_LOOKUP
#define SPP_NO_IS_ABSTRACT
#endif

#if __GNUC_MINOR__ < 4
#define SPP_NO_IS_ABSTRACT
#endif

#define SPP_NO_CXX11_EXTERN_TEMPLATE
#endif

#if __GNUC__ < 4
//
// All problems to gcc-3.x and earlier here:
//
#define SPP_NO_TWO_PHASE_NAME_LOOKUP
#ifdef __OPEN64__
#define SPP_NO_IS_ABSTRACT
#endif
#endif

// GCC prior to 3.4 had     #pragma once too but it didn't work well with
// filesystem links
#if SPP_GCC_VERSION >= 30400
#define SPP_HAS_PRAGMA_ONCE
#endif

#if SPP_GCC_VERSION < 40400
// Previous versions of GCC did not completely implement value-initialization:
// GCC Bug 30111, "Value-initialization of POD base class doesn't initialize
// members", reported by Jonathan Wakely in 2006,
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 (fixed for GCC 4.4)
// GCC Bug 33916, "Default constructor fails to initialize array members",
// reported by Michael Elizabeth Chastain in 2007,
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 (fixed for GCC 4.2.4)
// See also: http://www.boost.org/libs/utility/value_init.htm #compiler_issues
#define SPP_NO_COMPLETE_VALUE_INITIALIZATION
#endif

#if !defined(__EXCEPTIONS) && !defined(SPP_NO_EXCEPTIONS)
#define SPP_NO_EXCEPTIONS
#endif

//
// Threading support: Turn this on unconditionally here (except for
// those platforms where we can know for sure). It will get turned off again
// later if no threading API is detected.
//
#if !defined(__MINGW32__) && !defined(linux) && !defined(__linux) && \
    !defined(__linux__)
#define SPP_HAS_THREADS
#endif

//
// gcc has "long long"
// Except on Darwin with standard compliance enabled (-pedantic)
// Apple gcc helpfully defines this macro we can query
//
#if !defined(__DARWIN_NO_LONG_LONG)
#define SPP_HAS_LONG_LONG
#endif

//
// gcc implements the named return value optimization since version 3.1
//
#define SPP_HAS_NRVO

// Branch prediction hints
#define SPP_LIKELY(x) __builtin_expect(x, 1)
#define SPP_UNLIKELY(x) __builtin_expect(x, 0)

//
// Dynamic shared object (DSO) and dynamic-link library (DLL) support
//
#if __GNUC__ >= 4
#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \
    !defined(__CYGWIN__)
// All Win32 development environments, including 64-bit Windows and MinGW,
// define _WIN32 or one of its variant spellings. Note that Cygwin is a POSIX
// environment, so does not define _WIN32 or its variants.
#define SPP_HAS_DECLSPEC
#define SPP_SYMBOL_EXPORT __attribute__((__dllexport__))
#define SPP_SYMBOL_IMPORT __attribute__((__dllimport__))
#else
#define SPP_SYMBOL_EXPORT __attribute__((__visibility__("default")))
#define SPP_SYMBOL_IMPORT
#endif

#define SPP_SYMBOL_VISIBLE __attribute__((__visibility__("default")))
#else
// config/platform/win32.hpp will define SPP_SYMBOL_EXPORT, etc., unless already
// defined
#define SPP_SYMBOL_EXPORT
#endif

//
// RTTI and typeinfo detection is possible post gcc-4.3:
//
#if SPP_GCC_VERSION > 40300
#ifndef __GXX_RTTI
#ifndef SPP_NO_TYPEID
#define SPP_NO_TYPEID
#endif
#ifndef SPP_NO_RTTI
#define SPP_NO_RTTI
#endif
#endif
#endif

//
// Recent GCC versions have __int128 when in 64-bit mode.
//
// We disable this if the compiler is really nvcc with C++03 as it
// doesn't actually support __int128 as of CUDA_VERSION=7500
// even though it defines __SIZEOF_INT128__.
// See https://svn.boost.org/trac/boost/ticket/8048
//     https://svn.boost.org/trac/boost/ticket/11852
// Only re-enable this for nvcc if you're absolutely sure
// of the circumstances under which it's supported:
//
#if defined(__CUDACC__)
#if defined(SPP_GCC_CXX11)
#define SPP_NVCC_CXX11
#else
#define SPP_NVCC_CXX03
#endif
#endif

#if defined(__SIZEOF_INT128__) && !defined(SPP_NVCC_CXX03)
#define SPP_HAS_INT128
#endif
//
// Recent GCC versions have a __float128 native type, we need to
// include a std lib header to detect this - not ideal, but we'll
// be including <cstddef> later anyway when we select the std lib.
//
// Nevertheless, as of CUDA 7.5, using __float128 with the host
// compiler in pre-C++11 mode is still not supported.
// See https://svn.boost.org/trac/boost/ticket/11852
//
#ifdef __cplusplus
#include <cstddef>
#else
#include <stddef.h>
#endif

#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__) && \
    !defined(SPP_NVCC_CXX03)
#define SPP_HAS_FLOAT128
#endif

// C++0x features in 4.3.n and later
//
#if (SPP_GCC_VERSION >= 40300) && defined(SPP_GCC_CXX11)
// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are
// passed on the command line, which in turn defines
// __GXX_EXPERIMENTAL_CXX0X__.
#define SPP_HAS_DECLTYPE
#define SPP_HAS_RVALUE_REFS
#define SPP_HAS_STATIC_ASSERT
#define SPP_HAS_VARIADIC_TMPL
#define SPP_HAS_CSTDINT
#else
#define SPP_NO_CXX11_DECLTYPE
#define SPP_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
#define SPP_NO_CXX11_RVALUE_REFERENCES
#define SPP_NO_CXX11_STATIC_ASSERT
#endif

// C++0x features in 4.4.n and later
//
#if (SPP_GCC_VERSION < 40400) || !defined(SPP_GCC_CXX11)
#define SPP_NO_CXX11_AUTO_DECLARATIONS
#define SPP_NO_CXX11_AUTO_MULTIDECLARATIONS
#define SPP_NO_CXX11_CHAR16_T
#define SPP_NO_CXX11_CHAR32_T
#define SPP_NO_CXX11_HDR_INITIALIZER_LIST
#define SPP_NO_CXX11_DEFAULTED_FUNCTIONS
#define SPP_NO_CXX11_DELETED_FUNCTIONS
#define SPP_NO_CXX11_TRAILING_RESULT_TYPES
#define SPP_NO_CXX11_INLINE_NAMESPACES
#define SPP_NO_CXX11_VARIADIC_TEMPLATES
#endif

#if SPP_GCC_VERSION < 40500
#define SPP_NO_SFINAE_EXPR
#endif

// GCC 4.5 forbids declaration of defaulted functions in private or protected
// sections
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 5) || \
    !defined(SPP_GCC_CXX11)
#define SPP_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS
#endif

// C++0x features in 4.5.0 and later
//
#if (SPP_GCC_VERSION < 40500) || !defined(SPP_GCC_CXX11)
#define SPP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#define SPP_NO_CXX11_LAMBDAS
#define SPP_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
#define SPP_NO_CXX11_RAW_LITERALS
#endif

// C++0x features in 4.6.n and later
//
#if (SPP_GCC_VERSION < 40600) || !defined(SPP_GCC_CXX11)
#define SPP_NO_CXX11_CONSTEXPR
#define SPP_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
#endif

// C++0x features in 4.7.n and later
//
#if (SPP_GCC_VERSION < 40700) || !defined(SPP_GCC_CXX11)
#define SPP_NO_CXX11_FINAL
#define SPP_NO_CXX11_TEMPLATE_ALIASES
#define SPP_NO_CXX11_USER_DEFINED_LITERALS
#define SPP_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS
#endif

// C++0x features in 4.8.n and later
//
#if (SPP_GCC_VERSION < 40800) || !defined(SPP_GCC_CXX11)
#define SPP_NO_CXX11_ALIGNAS
#endif

// C++0x features in 4.8.1 and later
//
#if (SPP_GCC_VERSION < 40801) || !defined(SPP_GCC_CXX11)
#define SPP_NO_CXX11_DECLTYPE_N3276
#define SPP_NO_CXX11_REF_QUALIFIERS
#define SPP_NO_CXX14_BINARY_LITERALS
#endif

// C++14 features in 4.9.0 and later
//
#if (SPP_GCC_VERSION < 40900) || (__cplusplus < 201300)
#define SPP_NO_CXX14_RETURN_TYPE_DEDUCTION
#define SPP_NO_CXX14_GENERIC_LAMBDAS
#define SPP_NO_CXX14_DIGIT_SEPARATORS
#define SPP_NO_CXX14_DECLTYPE_AUTO
#if !((SPP_GCC_VERSION >= 40801) && (SPP_GCC_VERSION < 40900) && \
      defined(SPP_GCC_CXX11))
#define SPP_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
#endif
#endif

// C++ 14:
#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304)
#define SPP_NO_CXX14_CONSTEXPR
#endif
#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
#define SPP_NO_CXX14_VARIABLE_TEMPLATES
#endif

//
// Unused attribute:
#if __GNUC__ >= 4
#define SPP_ATTRIBUTE_UNUSED __attribute__((__unused__))
#endif
//
// __builtin_unreachable:
#if SPP_GCC_VERSION >= 40800
#define SPP_UNREACHABLE_RETURN(x) __builtin_unreachable();
#endif

#ifndef SPP_COMPILER
#define SPP_COMPILER "GNU C++ version " __VERSION__
#endif

// ConceptGCC compiler:
//   http://www.generic-programming.org/software/ConceptGCC/
#ifdef __GXX_CONCEPTS__
#define SPP_HAS_CONCEPTS
#define SPP_COMPILER "ConceptGCC version " __VERSION__
#endif

#elif defined _MSC_VER

#include <intrin.h>  // for __popcnt()

#define SPP_POPCNT_CHECK  // slower when defined, but we have to check!
#define spp_cpuid(info, x) __cpuid(info, x)

#define SPP_POPCNT __popcnt
#if (SPP_GROUP_SIZE == 64 && INTPTR_MAX == INT64_MAX)
#define SPP_POPCNT64 __popcnt64
#endif

// Attempt to suppress VC6 warnings about the length of decorated names
// (obsolete):
#pragma warning(disable : 4503)  // warning: decorated name length exceeded

#define SPP_HAS_PRAGMA_ONCE
#define SPP_HAS_CSTDINT

//
// versions check:
// we don't support Visual C++ prior to version 7.1:
#if _MSC_VER < 1310
#error "Antique compiler not supported"
#endif

#if _MSC_FULL_VER < 180020827
#define SPP_NO_FENV_H
#endif

#if _MSC_VER < 1400
// although a conforming signature for swprint exists in VC7.1
// it appears not to actually work:
#define SPP_NO_SWPRINTF

// Our extern template tests also fail for this compiler:
#define SPP_NO_CXX11_EXTERN_TEMPLATE

// Variadic macros do not exist for VC7.1 and lower
#define SPP_NO_CXX11_VARIADIC_MACROS
#endif

#if _MSC_VER < 1500  // 140X == VC++ 8.0
#undef SPP_HAS_CSTDINT
#define SPP_NO_MEMBER_TEMPLATE_FRIENDS
#endif

#if _MSC_VER < 1600  // 150X == VC++ 9.0
// A bug in VC9:
#define SPP_NO_ADL_BARRIER
#endif

// MSVC (including the latest checked version) has not yet completely
// implemented value-initialization, as is reported:
// "VC++ does not value-initialize members of derived classes without
// user-declared constructor", reported in 2009 by Sylvester Hesp:
// https:    //connect.microsoft.com/VisualStudio/feedback/details/484295
// "Presence of copy constructor breaks member class initialization",
// reported in 2009 by Alex Vakulenko:
// https:    //connect.microsoft.com/VisualStudio/feedback/details/499606
// "Value-initialization in new-expression", reported in 2005 by
// Pavel Kuznetsov (MetaCommunications Engineering):
// https:    //connect.microsoft.com/VisualStudio/feedback/details/100744
// See also: http:    //www.boost.org/libs/utility/value_init.htm
// #compiler_issues (Niels Dekker, LKEB, May 2010)
#define SPP_NO_COMPLETE_VALUE_INITIALIZATION

#ifndef _NATIVE_WCHAR_T_DEFINED
#define SPP_NO_INTRINSIC_WCHAR_T
#endif

//
// check for exception handling support:
#if !defined(_CPPUNWIND) && !defined(SPP_NO_EXCEPTIONS)
#define SPP_NO_EXCEPTIONS
#endif

//
// __int64 support:
//
#define SPP_HAS_MS_INT64
#if defined(_MSC_EXTENSIONS) || (_MSC_VER >= 1400)
#define SPP_HAS_LONG_LONG
#else
#define SPP_NO_LONG_LONG
#endif

#if (_MSC_VER >= 1400) && !defined(_DEBUG)
#define SPP_HAS_NRVO
#endif

#if _MSC_VER >= 1500  // 150X == VC++ 9.0
#define SPP_HAS_PRAGMA_DETECT_MISMATCH
#endif

//
// disable Win32 API's if compiler extensions are
// turned off:
//
#if !defined(_MSC_EXTENSIONS) && !defined(SPP_DISABLE_WIN32)
#define SPP_DISABLE_WIN32
#endif

#if !defined(_CPPRTTI) && !defined(SPP_NO_RTTI)
#define SPP_NO_RTTI
#endif

//
// TR1 features:
//
#if _MSC_VER >= 1700
//      #define SPP_HAS_TR1_HASH	// don't know if this is true yet.
//      #define SPP_HAS_TR1_TYPE_TRAITS	// don't know if this is true yet.
#define SPP_HAS_TR1_UNORDERED_MAP
#define SPP_HAS_TR1_UNORDERED_SET
#endif

//
// C++0x features
//
//   See above for SPP_NO_LONG_LONG

// C++ features supported by VC++ 10 (aka 2010)
//
#if _MSC_VER < 1600
#define SPP_NO_CXX11_AUTO_DECLARATIONS
#define SPP_NO_CXX11_AUTO_MULTIDECLARATIONS
#define SPP_NO_CXX11_LAMBDAS
#define SPP_NO_CXX11_RVALUE_REFERENCES
#define SPP_NO_CXX11_STATIC_ASSERT
#define SPP_NO_CXX11_DECLTYPE
#endif  // _MSC_VER < 1600

#if _MSC_VER >= 1600
#define SPP_HAS_STDINT_H
#endif

// C++11 features supported by VC++ 11 (aka 2012)
//
#if _MSC_VER < 1700
#define SPP_NO_CXX11_FINAL
#endif  // _MSC_VER < 1700

// C++11 features supported by VC++ 12 (aka 2013).
//
#if _MSC_FULL_VER < 180020827
#define SPP_NO_CXX11_DEFAULTED_FUNCTIONS
#define SPP_NO_CXX11_DELETED_FUNCTIONS
#define SPP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#define SPP_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
#define SPP_NO_CXX11_RAW_LITERALS
#define SPP_NO_CXX11_TEMPLATE_ALIASES
#define SPP_NO_CXX11_TRAILING_RESULT_TYPES
#define SPP_NO_CXX11_VARIADIC_TEMPLATES
#define SPP_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
#define SPP_NO_CXX11_DECLTYPE_N3276
#endif

// C++11 features supported by VC++ 14 (aka 2014) CTP1
#if (_MSC_FULL_VER < 190021730)
#define SPP_NO_CXX11_REF_QUALIFIERS
#define SPP_NO_CXX11_USER_DEFINED_LITERALS
#define SPP_NO_CXX11_ALIGNAS
#define SPP_NO_CXX11_INLINE_NAMESPACES
#define SPP_NO_CXX14_DECLTYPE_AUTO
#define SPP_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
#define SPP_NO_CXX14_RETURN_TYPE_DEDUCTION
#define SPP_NO_CXX11_HDR_INITIALIZER_LIST
#endif

// C++11 features not supported by any versions
#define SPP_NO_CXX11_CHAR16_T
#define SPP_NO_CXX11_CHAR32_T
#define SPP_NO_CXX11_CONSTEXPR
#define SPP_NO_SFINAE_EXPR
#define SPP_NO_TWO_PHASE_NAME_LOOKUP

// C++ 14:
#if !defined(__cpp_binary_literals) || (__cpp_binary_literals < 201304)
#define SPP_NO_CXX14_BINARY_LITERALS
#endif

#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304)
#define SPP_NO_CXX14_CONSTEXPR
#endif

#if (__cplusplus < 201304)  // There's no SD6 check for this....
#define SPP_NO_CXX14_DIGIT_SEPARATORS
#endif

#if !defined(__cpp_generic_lambdas) || (__cpp_generic_lambdas < 201304)
#define SPP_NO_CXX14_GENERIC_LAMBDAS
#endif

#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
#define SPP_NO_CXX14_VARIABLE_TEMPLATES
#endif

#endif

// from boost/config/suffix.hpp
// ----------------------------
#ifndef SPP_ATTRIBUTE_UNUSED
#define SPP_ATTRIBUTE_UNUSED
#endif

/*
  Try to persuade compilers to inline.
*/
#ifndef SPP_FORCEINLINE
#if defined(__GNUC__)
#define SPP_FORCEINLINE __inline __attribute__((always_inline))
#elif defined(_MSC_VER)
#define SPP_FORCEINLINE __forceinline
#else
#define SPP_FORCEINLINE inline
#endif
#endif

#endif  // spp_config_h_guard
