Apple Clang12定义__cpp_lib_hardware_interference_size却无对应std符号如何处理?
问题原因
你遇到的是Apple Clang 12的已知兼容bug:该版本的libc++头文件<new>错误提前定义了__cpp_lib_hardware_interference_size特性宏,但实际并未实现std::hardware_constructive_interference_size和std::hardware_destructive_interference_size两个标准常量,该问题在Xcode 13/Apple Clang 13及以上版本已修复。
解决方法
可根据你的需求选择以下任意一种方案:
方案1:调整宏判断逻辑,增加平台版本过滤
改动最小的适配方案,在原有宏判断基础上增加Apple平台的编译器版本校验,规避存在bug的版本,修改后的代码如下:
#include <new> #include <cstddef> #if defined(__cpp_lib_hardware_interference_size) && !(defined(__APPLE__) && __clang_major__ < 13) using std::hardware_constructive_interference_size; using std::hardware_destructive_interference_size; #else // x86_64架构L1缓存行固定为64字节,比通用计算逻辑更适配你的当前环境 constexpr std::size_t hardware_constructive_interference_size = 64; constexpr std::size_t hardware_destructive_interference_size = 64; #endif
方案2:编译期检测符号是否存在(SFINAE实现)
跨平台通用方案,不依赖平台版本判断,通过C++模板的SFINAE特性在编译期自动检测符号是否存在,代码示例如下:
#include <new> #include <cstddef> #include <type_traits> namespace detail { template <typename = void> struct interference_size_provider { static constexpr std::size_t constructive = 64; static constexpr std::size_t destructive = 64; }; template <typename T> requires requires { T::hardware_constructive_interference_size; } struct interference_size_provider<std::void_t<decltype(std::hardware_constructive_interference_size)>> { static constexpr std::size_t constructive = std::hardware_constructive_interference_size; static constexpr std::size_t destructive = std::hardware_destructive_interference_size; }; } constexpr std::size_t hardware_constructive_interference_size = detail::interference_size_provider<>::constructive; constexpr std::size_t hardware_destructive_interference_size = detail::interference_size_provider<>::destructive;
该方案可在所有C++17及以上的编译器环境下正常工作,不需要依赖任何特性宏。
方案3:CMake侧提前检测(适配你的构建环境)
你使用CMake作为构建工具,可以直接用CMake内置的CheckCXXSymbolExists模块在配置阶段就检测符号是否存在,自动给代码传递宏定义:
首先修改CMakeLists.txt,增加检测逻辑:
cmake_minimum_required(VERSION 3.19) project(untitled4) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") if (UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") endif() # 新增硬件干扰大小符号检测逻辑 include(CheckCXXSymbolExists) check_cxx_symbol_exists(std::hardware_constructive_interference_size "new" HAVE_HW_INTERFERENCE_SIZE) if (HAVE_HW_INTERFERENCE_SIZE) target_compile_definitions(untitled4 PRIVATE HAVE_HW_INTERFERENCE_SIZE) endif() add_executable(untitled4 main.cpp)
然后修改C++代码中的判断逻辑:
#include <new> #include <cstddef> #ifdef HAVE_HW_INTERFERENCE_SIZE using std::hardware_constructive_interference_size; using std::hardware_destructive_interference_size; #else constexpr std::size_t hardware_constructive_interference_size = 64; constexpr std::size_t hardware_destructive_interference_size = 64; #endif
该方案把检测逻辑移到构建阶段,避免C++代码中做复杂的平台版本判断。
内容的提问来源于stack exchange,提问作者김선달
相关产品推荐
相关产品推荐

