github.com/moontrade/nogc@v0.1.7/collections/tree/Portability.h (about)

     1  /*
     2   * Copyright (c) Facebook, Inc. and its affiliates.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #pragma once
    18  
    19  #include <cstddef>
    20  
    21  #include "CPortability.h"
    22  #include "PortabilityConfig.h"
    23  
    24  #if defined(_MSC_VER)
    25  #define FOLLY_CPLUSPLUS _MSVC_LANG
    26  #else
    27  #define FOLLY_CPLUSPLUS __cplusplus
    28  #endif
    29  
    30  static_assert(FOLLY_CPLUSPLUS >= 201402L, "__cplusplus >= 201402L");
    31  
    32  #if defined(__GNUC__) && !defined(__clang__)
    33  static_assert(__GNUC__ >= 5, "__GNUC__ >= 5");
    34  #endif
    35  
    36  // Unaligned loads and stores
    37  namespace folly {
    38  #if FOLLY_HAVE_UNALIGNED_ACCESS
    39  constexpr bool kHasUnalignedAccess = true;
    40  #else
    41  constexpr bool kHasUnalignedAccess = false;
    42  #endif
    43  } // namespace folly
    44  
    45  // compiler specific attribute translation
    46  // msvc should come first, so if clang is in msvc mode it gets the right defines
    47  
    48  // NOTE: this will only do checking in msvc with versions that support /analyze
    49  #if _MSC_VER
    50  #ifdef _USE_ATTRIBUTES_FOR_SAL
    51  #undef _USE_ATTRIBUTES_FOR_SAL
    52  #endif
    53  /* nolint */
    54  #define _USE_ATTRIBUTES_FOR_SAL 1
    55  #include <sal.h> // @manual
    56  #define FOLLY_PRINTF_FORMAT _Printf_format_string_
    57  #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/
    58  #else
    59  #define FOLLY_PRINTF_FORMAT /**/
    60  #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) \
    61    __attribute__((__format__(__printf__, format_param, dots_param)))
    62  #endif
    63  
    64  // warn unused result
    65  #if defined(__has_cpp_attribute)
    66  #if __has_cpp_attribute(nodiscard)
    67  #define FOLLY_NODISCARD [[nodiscard]]
    68  #endif
    69  #endif
    70  #if !defined FOLLY_NODISCARD
    71  #if defined(_MSC_VER) && (_MSC_VER >= 1700)
    72  #define FOLLY_NODISCARD _Check_return_
    73  #elif defined(__GNUC__)
    74  #define FOLLY_NODISCARD __attribute__((__warn_unused_result__))
    75  #else
    76  #define FOLLY_NODISCARD
    77  #endif
    78  #endif
    79  
    80  // target
    81  #ifdef _MSC_VER
    82  #define FOLLY_TARGET_ATTRIBUTE(target)
    83  #else
    84  #define FOLLY_TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
    85  #endif
    86  
    87  // detection for 64 bit
    88  #if defined(__x86_64__) || defined(_M_X64)
    89  #define FOLLY_X64 1
    90  #else
    91  #define FOLLY_X64 0
    92  #endif
    93  
    94  #if defined(__arm__)
    95  #define FOLLY_ARM 1
    96  #else
    97  #define FOLLY_ARM 0
    98  #endif
    99  
   100  #if defined(__aarch64__)
   101  #define FOLLY_AARCH64 1
   102  #else
   103  #define FOLLY_AARCH64 0
   104  #endif
   105  
   106  #if defined(__powerpc64__)
   107  #define FOLLY_PPC64 1
   108  #else
   109  #define FOLLY_PPC64 0
   110  #endif
   111  
   112  #if defined(__s390x__)
   113  #define FOLLY_S390X 1
   114  #else
   115  #define FOLLY_S390X 0
   116  #endif
   117  
   118  namespace folly {
   119  constexpr bool kIsArchArm = FOLLY_ARM == 1;
   120  constexpr bool kIsArchAmd64 = FOLLY_X64 == 1;
   121  constexpr bool kIsArchAArch64 = FOLLY_AARCH64 == 1;
   122  constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1;
   123  constexpr bool kIsArchS390X = FOLLY_S390X == 1;
   124  } // namespace folly
   125  
   126  namespace folly {
   127  
   128  /**
   129   * folly::kIsLibrarySanitizeAddress reports if folly was compiled with ASAN
   130   * enabled.  Note that for compilation units outside of folly that include
   131   * folly/Portability.h, the value of kIsLibrarySanitizeAddress may be different
   132   * from whether or not the current compilation unit is being compiled with ASAN.
   133   */
   134  #if FOLLY_LIBRARY_SANITIZE_ADDRESS
   135  constexpr bool kIsLibrarySanitizeAddress = true;
   136  #else
   137  constexpr bool kIsLibrarySanitizeAddress = false;
   138  #endif
   139  
   140  #if FOLLY_SANITIZE_ADDRESS
   141  constexpr bool kIsSanitizeAddress = true;
   142  #else
   143  constexpr bool kIsSanitizeAddress = false;
   144  #endif
   145  
   146  #if FOLLY_SANITIZE_THREAD
   147  constexpr bool kIsSanitizeThread = true;
   148  #else
   149  constexpr bool kIsSanitizeThread = false;
   150  #endif
   151  
   152  #if FOLLY_SANITIZE
   153  constexpr bool kIsSanitize = true;
   154  #else
   155  constexpr bool kIsSanitize = false;
   156  #endif
   157  } // namespace folly
   158  
   159  // packing is very ugly in msvc
   160  #ifdef _MSC_VER
   161  #define FOLLY_PACK_ATTR /**/
   162  #define FOLLY_PACK_PUSH __pragma(pack(push, 1))
   163  #define FOLLY_PACK_POP __pragma(pack(pop))
   164  #elif defined(__GNUC__)
   165  #define FOLLY_PACK_ATTR __attribute__((__packed__))
   166  #define FOLLY_PACK_PUSH /**/
   167  #define FOLLY_PACK_POP /**/
   168  #else
   169  #define FOLLY_PACK_ATTR /**/
   170  #define FOLLY_PACK_PUSH /**/
   171  #define FOLLY_PACK_POP /**/
   172  #endif
   173  
   174  // Generalize warning push/pop.
   175  #if defined(__GNUC__) || defined(__clang__)
   176  // Clang & GCC
   177  #define FOLLY_PUSH_WARNING _Pragma("GCC diagnostic push")
   178  #define FOLLY_POP_WARNING _Pragma("GCC diagnostic pop")
   179  #define FOLLY_GNU_DISABLE_WARNING_INTERNAL2(warningName) #warningName
   180  #define FOLLY_GNU_DISABLE_WARNING(warningName) \
   181    _Pragma(                                     \
   182        FOLLY_GNU_DISABLE_WARNING_INTERNAL2(GCC diagnostic ignored warningName))
   183  #ifdef __clang__
   184  #define FOLLY_CLANG_DISABLE_WARNING(warningName) \
   185    FOLLY_GNU_DISABLE_WARNING(warningName)
   186  #define FOLLY_GCC_DISABLE_WARNING(warningName)
   187  #else
   188  #define FOLLY_CLANG_DISABLE_WARNING(warningName)
   189  #define FOLLY_GCC_DISABLE_WARNING(warningName) \
   190    FOLLY_GNU_DISABLE_WARNING(warningName)
   191  #endif
   192  #define FOLLY_MSVC_DISABLE_WARNING(warningNumber)
   193  #elif defined(_MSC_VER)
   194  #define FOLLY_PUSH_WARNING __pragma(warning(push))
   195  #define FOLLY_POP_WARNING __pragma(warning(pop))
   196  // Disable the GCC warnings.
   197  #define FOLLY_GNU_DISABLE_WARNING(warningName)
   198  #define FOLLY_GCC_DISABLE_WARNING(warningName)
   199  #define FOLLY_CLANG_DISABLE_WARNING(warningName)
   200  #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) \
   201    __pragma(warning(disable : warningNumber))
   202  #else
   203  #define FOLLY_PUSH_WARNING
   204  #define FOLLY_POP_WARNING
   205  #define FOLLY_GNU_DISABLE_WARNING(warningName)
   206  #define FOLLY_GCC_DISABLE_WARNING(warningName)
   207  #define FOLLY_CLANG_DISABLE_WARNING(warningName)
   208  #define FOLLY_MSVC_DISABLE_WARNING(warningNumber)
   209  #endif
   210  
   211  #ifdef FOLLY_HAVE_SHADOW_LOCAL_WARNINGS
   212  #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS            \
   213    FOLLY_GNU_DISABLE_WARNING("-Wshadow-compatible-local") \
   214    FOLLY_GNU_DISABLE_WARNING("-Wshadow-local")            \
   215    FOLLY_GNU_DISABLE_WARNING("-Wshadow")
   216  #else
   217  #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS /* empty */
   218  #endif
   219  
   220  // It turns out that GNU libstdc++ and LLVM libc++ differ on how they implement
   221  // the 'std' namespace; the latter uses inline namespaces. Wrap this decision
   222  // up in a macro to make forward-declarations easier.
   223  #if FOLLY_USE_LIBCPP
   224  #include <__config> // @manual
   225  #define FOLLY_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
   226  #define FOLLY_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD
   227  #else
   228  #define FOLLY_NAMESPACE_STD_BEGIN namespace std {
   229  #define FOLLY_NAMESPACE_STD_END }
   230  #endif
   231  
   232  // If the new c++ ABI is used, __cxx11 inline namespace needs to be added to
   233  // some types, e.g. std::list.
   234  #if _GLIBCXX_USE_CXX11_ABI
   235  #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN \
   236    inline _GLIBCXX_BEGIN_NAMESPACE_CXX11
   237  #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END _GLIBCXX_END_NAMESPACE_CXX11
   238  #else
   239  #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN
   240  #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END
   241  #endif
   242  
   243  // MSVC specific defines
   244  // mainly for posix compat
   245  #ifdef _MSC_VER
   246  #include <folly/portability/SysTypes.h>
   247  
   248  // Hide a GCC specific thing that breaks MSVC if left alone.
   249  #define __extension__
   250  
   251  // We have compiler support for the newest of the new, but
   252  // MSVC doesn't tell us that.
   253  //
   254  // Clang pretends to be MSVC on Windows, but it refuses to compile
   255  // SSE4.2 intrinsics unless -march argument is specified.
   256  // So cannot unconditionally define __SSE4_2__ in clang.
   257  #ifndef __clang__
   258  #if !defined(_M_ARM) && !defined(_M_ARM64)
   259  #define __SSE4_2__ 1
   260  #endif // !defined(_M_ARM) && !defined(_M_ARM64)
   261  
   262  // compiler specific to compiler specific
   263  // nolint
   264  #define __PRETTY_FUNCTION__ __FUNCSIG__
   265  #endif
   266  
   267  #endif
   268  
   269  // Define FOLLY_HAS_EXCEPTIONS
   270  #if __cpp_exceptions >= 199711 || FOLLY_HAS_FEATURE(cxx_exceptions)
   271  #define FOLLY_HAS_EXCEPTIONS 1
   272  #elif __GNUC__
   273  #if __EXCEPTIONS
   274  #define FOLLY_HAS_EXCEPTIONS 1
   275  #else // __EXCEPTIONS
   276  #define FOLLY_HAS_EXCEPTIONS 0
   277  #endif // __EXCEPTIONS
   278  #elif FOLLY_MICROSOFT_ABI_VER
   279  #if _CPPUNWIND
   280  #define FOLLY_HAS_EXCEPTIONS 1
   281  #else // _CPPUNWIND
   282  #define FOLLY_HAS_EXCEPTIONS 0
   283  #endif // _CPPUNWIND
   284  #else
   285  #define FOLLY_HAS_EXCEPTIONS 1 // default assumption for unknown platforms
   286  #endif
   287  
   288  // Debug
   289  namespace folly {
   290  #ifdef NDEBUG
   291  constexpr auto kIsDebug = false;
   292  #else
   293  constexpr auto kIsDebug = true;
   294  #endif
   295  } // namespace folly
   296  
   297  // Exceptions
   298  namespace folly {
   299  #if FOLLY_HAS_EXCEPTIONS
   300  constexpr auto kHasExceptions = true;
   301  #else
   302  constexpr auto kHasExceptions = false;
   303  #endif
   304  } // namespace folly
   305  
   306  // Endianness
   307  namespace folly {
   308  #ifdef _MSC_VER
   309  // It's MSVC, so we just have to guess ... and allow an override
   310  #ifdef FOLLY_ENDIAN_BE
   311  constexpr auto kIsLittleEndian = false;
   312  #else
   313  constexpr auto kIsLittleEndian = true;
   314  #endif
   315  #else
   316  constexpr auto kIsLittleEndian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
   317  #endif
   318  constexpr auto kIsBigEndian = !kIsLittleEndian;
   319  } // namespace folly
   320  
   321  // Weak
   322  namespace folly {
   323  #if FOLLY_HAVE_WEAK_SYMBOLS
   324  constexpr auto kHasWeakSymbols = true;
   325  #else
   326  constexpr auto kHasWeakSymbols = false;
   327  #endif
   328  } // namespace folly
   329  
   330  #ifndef FOLLY_SSE
   331  #if defined(__SSE4_2__)
   332  #define FOLLY_SSE 4
   333  #define FOLLY_SSE_MINOR 2
   334  #elif defined(__SSE4_1__)
   335  #define FOLLY_SSE 4
   336  #define FOLLY_SSE_MINOR 1
   337  #elif defined(__SSE4__)
   338  #define FOLLY_SSE 4
   339  #define FOLLY_SSE_MINOR 0
   340  #elif defined(__SSE3__)
   341  #define FOLLY_SSE 3
   342  #define FOLLY_SSE_MINOR 0
   343  #elif defined(__SSE2__)
   344  #define FOLLY_SSE 2
   345  #define FOLLY_SSE_MINOR 0
   346  #elif defined(__SSE__)
   347  #define FOLLY_SSE 1
   348  #define FOLLY_SSE_MINOR 0
   349  #else
   350  #define FOLLY_SSE 0
   351  #define FOLLY_SSE_MINOR 0
   352  #endif
   353  #endif
   354  
   355  #ifndef FOLLY_SSSE
   356  #if defined(__SSSE3__)
   357  #define FOLLY_SSSE 3
   358  #else
   359  #define FOLLY_SSSE 0
   360  #endif
   361  #endif
   362  
   363  #define FOLLY_SSE_PREREQ(major, minor) \
   364    (FOLLY_SSE > major || FOLLY_SSE == major && FOLLY_SSE_MINOR >= minor)
   365  
   366  #ifndef FOLLY_NEON
   367  #if defined(__ARM_NEON) || defined(__ARM_NEON__)
   368  #define FOLLY_NEON 1
   369  #endif
   370  #endif
   371  
   372  #if FOLLY_UNUSUAL_GFLAGS_NAMESPACE
   373  namespace FOLLY_GFLAGS_NAMESPACE {}
   374  namespace gflags {
   375  using namespace FOLLY_GFLAGS_NAMESPACE;
   376  } // namespace gflags
   377  #endif
   378  
   379  // RTTI may not be enabled for this compilation unit.
   380  #if defined(__GXX_RTTI) || defined(__cpp_rtti) || \
   381      (defined(_MSC_VER) && defined(_CPPRTTI))
   382  #define FOLLY_HAS_RTTI 1
   383  #else
   384  #define FOLLY_HAS_RTTI 0
   385  #endif
   386  
   387  namespace folly {
   388  constexpr bool const kHasRtti = FOLLY_HAS_RTTI;
   389  } // namespace folly
   390  
   391  #if defined(__APPLE__) || defined(_MSC_VER)
   392  #define FOLLY_STATIC_CTOR_PRIORITY_MAX
   393  #else
   394  // 101 is the highest priority allowed by the init_priority attribute.
   395  // This priority is already used by JEMalloc and other memory allocators so
   396  // we will take the next one.
   397  #define FOLLY_STATIC_CTOR_PRIORITY_MAX __attribute__((__init_priority__(102)))
   398  #endif
   399  
   400  #if defined(__APPLE__) && TARGET_OS_IOS
   401  #define FOLLY_APPLE_IOS 1
   402  #else
   403  #define FOLLY_APPLE_IOS 0
   404  #endif
   405  
   406  #if defined(__APPLE__) && TARGET_OS_OSX
   407  #define FOLLY_APPLE_MACOS 1
   408  #else
   409  #define FOLLY_APPLE_MACOS 0
   410  #endif
   411  
   412  #if defined(__APPLE__) && TARGET_OS_TV
   413  #define FOLLY_APPLE_TVOS 1
   414  #else
   415  #define FOLLY_APPLE_TVOS 0
   416  #endif
   417  
   418  #if defined(__APPLE__) && TARGET_OS_WATCH
   419  #define FOLLY_APPLE_WATCHOS 1
   420  #else
   421  #define FOLLY_APPLE_WATCHOS 0
   422  #endif
   423  
   424  namespace folly {
   425  
   426  #if __OBJC__
   427  constexpr auto kIsObjC = true;
   428  #else
   429  constexpr auto kIsObjC = false;
   430  #endif
   431  
   432  #if FOLLY_MOBILE
   433  constexpr auto kIsMobile = true;
   434  #else
   435  constexpr auto kIsMobile = false;
   436  #endif
   437  
   438  #if defined(__linux__) && !FOLLY_MOBILE
   439  constexpr auto kIsLinux = true;
   440  #else
   441  constexpr auto kIsLinux = false;
   442  #endif
   443  
   444  #if defined(_WIN32)
   445  constexpr auto kIsWindows = true;
   446  #else
   447  constexpr auto kIsWindows = false;
   448  #endif
   449  
   450  #if defined(__APPLE__)
   451  constexpr auto kIsApple = true;
   452  #else
   453  constexpr auto kIsApple = false;
   454  #endif
   455  
   456  constexpr bool kIsAppleIOS = FOLLY_APPLE_IOS == 1;
   457  constexpr bool kIsAppleMacOS = FOLLY_APPLE_MACOS == 1;
   458  constexpr bool kIsAppleTVOS = FOLLY_APPLE_TVOS == 1;
   459  constexpr bool kIsAppleWatchOS = FOLLY_APPLE_WATCHOS == 1;
   460  
   461  #if __GLIBCXX__
   462  constexpr auto kIsGlibcxx = true;
   463  #else
   464  constexpr auto kIsGlibcxx = false;
   465  #endif
   466  
   467  #if __GLIBCXX__ && _GLIBCXX_RELEASE // major version, 7+
   468  constexpr auto kGlibcxxVer = _GLIBCXX_RELEASE;
   469  #else
   470  constexpr auto kGlibcxxVer = 0;
   471  #endif
   472  
   473  #if __GLIBCXX__ && defined(_GLIBCXX_ASSERTIONS)
   474  constexpr auto kGlibcxxAssertions = true;
   475  #else
   476  constexpr auto kGlibcxxAssertions = false;
   477  #endif
   478  
   479  #if _LIBCPP_VERSION
   480  constexpr auto kIsLibcpp = true;
   481  #else
   482  constexpr auto kIsLibcpp = false;
   483  #endif
   484  
   485  #if FOLLY_USE_LIBSTDCPP
   486  constexpr auto kIsLibstdcpp = true;
   487  #else
   488  constexpr auto kIsLibstdcpp = false;
   489  #endif
   490  
   491  #if _MSC_VER
   492  constexpr auto kMscVer = _MSC_VER;
   493  #else
   494  constexpr auto kMscVer = 0;
   495  #endif
   496  
   497  #if __GNUC__
   498  constexpr auto kGnuc = __GNUC__;
   499  #else
   500  constexpr auto kGnuc = 0;
   501  #endif
   502  
   503  #if __clang__
   504  constexpr auto kIsClang = true;
   505  constexpr auto kClangVerMajor = __clang_major__;
   506  #else
   507  constexpr auto kIsClang = false;
   508  constexpr auto kClangVerMajor = 0;
   509  #endif
   510  
   511  #if FOLLY_MICROSOFT_ABI_VER
   512  constexpr auto kMicrosoftAbiVer = FOLLY_MICROSOFT_ABI_VER;
   513  #else
   514  constexpr auto kMicrosoftAbiVer = 0;
   515  #endif
   516  
   517  // cpplib is an implementation of the standard library, and is the one typically
   518  // used with the msvc compiler
   519  #if _CPPLIB_VER
   520  constexpr auto kCpplibVer = _CPPLIB_VER;
   521  #else
   522  constexpr auto kCpplibVer = 0;
   523  #endif
   524  } // namespace folly
   525  
   526  //  MSVC does not permit:
   527  //
   528  //    extern int const num;
   529  //    constexpr int const num = 3;
   530  //
   531  //  Instead:
   532  //
   533  //    extern int const num;
   534  //    FOLLY_STORAGE_CONSTEXPR int const num = 3;
   535  //
   536  //  True as of MSVC 2017.
   537  #if _MSC_VER
   538  #define FOLLY_STORAGE_CONSTEXPR
   539  #else
   540  #define FOLLY_STORAGE_CONSTEXPR constexpr
   541  #endif
   542  
   543  #if __cplusplus >= 201703L
   544  // folly::coro requires C++17 support
   545  #if defined(_WIN32) && defined(__clang__) && !defined(LLVM_COROUTINES)
   546  // LLVM and MSVC coroutines are ABI incompatible, so for the MSVC implementation
   547  // of <experimental/coroutine> on Windows we *don't* have coroutines.
   548  //
   549  // LLVM_COROUTINES indicates that LLVM compatible header is added to include
   550  // path and can be used.
   551  //
   552  // Worse, if we define FOLLY_HAS_COROUTINES 1 we will include
   553  // <experimental/coroutine> which will conflict with anyone who wants to load
   554  // the LLVM implementation of coroutines on Windows.
   555  #define FOLLY_HAS_COROUTINES 0
   556  #elif (__cpp_coroutines >= 201703L || __cpp_impl_coroutine >= 201902L) && \
   557      (__has_include(<coroutine>) || __has_include(<experimental/coroutine>))
   558  #define FOLLY_HAS_COROUTINES 1
   559  // This is mainly to workaround bugs triggered by LTO, when stack allocated
   560  // variables in await_suspend end up on a coroutine frame.
   561  #define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE
   562  #elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED
   563  // NOTE: MSVC 2017 does not currently support the full Coroutines TS since it
   564  // does not yet support symmetric-transfer.
   565  #define FOLLY_HAS_COROUTINES 0
   566  #else
   567  #define FOLLY_HAS_COROUTINES 0
   568  #endif
   569  #else
   570  #define FOLLY_HAS_COROUTINES 0
   571  #endif // __cplusplus >= 201703L
   572  
   573  // MSVC 2017.5 && C++17
   574  #if __cpp_noexcept_function_type >= 201510 || \
   575      (_MSC_FULL_VER >= 191225816 && _MSVC_LANG > 201402)
   576  #define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1
   577  #endif
   578  
   579  #if __cpp_inline_variables >= 201606L
   580  #define FOLLY_HAS_INLINE_VARIABLES 1
   581  #define FOLLY_INLINE_VARIABLE inline
   582  #else
   583  #define FOLLY_HAS_INLINE_VARIABLES 0
   584  #define FOLLY_INLINE_VARIABLE
   585  #endif
   586  
   587  // feature test __cpp_lib_string_view is defined in <string>, which is
   588  // too heavy to include here.
   589  #if __has_include(<string_view>) && FOLLY_CPLUSPLUS >= 201703L
   590  #define FOLLY_HAS_STRING_VIEW 1
   591  #else
   592  #define FOLLY_HAS_STRING_VIEW 0
   593  #endif