当前位置: 首页 > ds >正文

UE4 Mac构建编译报错 no template named “is_void_v” in namespace “std”

背景

UE4 Mac构建编译报错 no template named “is_void_v” in namespace “std” ,但WINDOWS没有遇到错误。

分析过程

1、is_void_v 是否属于C++17

从语法上看,AI说不只是 C++17 才有。早在C++14 就有 is_void_v 的用法了。


2、WINDOWS中is_void_v的定义

这段代码在WINDOWS下定义在
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\include\type_traits


3、Mac中is_void_v的定义

在WINDOWS中,is_void_v 的定义是在: C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\include\type_traits ,那么在Mac机器中,它可能定义在哪个路径下?
我找到了它在Mac机器上的定义,位于:/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__type_traits/is_void.h ,具体定义是:

//代码1:
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//#ifndef _LIBCPP___TYPE_TRAITS_IS_VOID_H
#define _LIBCPP___TYPE_TRAITS_IS_VOID_H#include <__config>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_same.h>
#include <__type_traits/remove_cv.h>#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#  pragma GCC system_header
#endif_LIBCPP_BEGIN_NAMESPACE_STD#if __has_builtin(__is_void)template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS is_void : _BoolConstant<__is_void(_Tp)> {};#  if _LIBCPP_STD_VER >= 17
template <class _Tp>
inline constexpr bool is_void_v = __is_void(_Tp);
#  endif#elsetemplate <class _Tp>
struct _LIBCPP_TEMPLATE_VIS is_void : public is_same<__remove_cv_t<_Tp>, void> {};#  if _LIBCPP_STD_VER >= 17
template <class _Tp>
inline constexpr bool is_void_v = is_void<_Tp>::value;
#  endif#endif // __has_builtin(__is_void)_LIBCPP_END_NAMESPACE_STD#endif // _LIBCPP___TYPE_TRAITS_IS_VOID_H

4、_LIBCPP_STD_VER的含义

_LIBCPP_STD_VER是 ​libc++(LLVM 的 C++ 标准库实现)内部用来表示其当前所支持的 C++ 标准版本的一个宏。它的值是一个整数,对应了不同的 C++ 标准发布年份。
这个宏的主要作用是让 libc++ 的代码能够根据不同的 C++ 标准版本条件地编译某些特性或提供特定版本的 API。以下是 _LIBCPP_STD_VER常见值及其对应的 C++ 标准的梳理:

#  if _LIBCPP_STD_VER >= 17
template <class _Tp>
inline constexpr bool is_void_v = __is_void(_Tp); // 或者 = is_void<_Tp>::value;
#  endif

上述代码意味着 ​is_void_v这个变量模板只有在 C++17 或更高版本下才会被定义和提供。这很好地解释了你最初的问题:is_void_v确实是 C++17 引入的特性。

5、理解 _LIBCPP_STD_VER与 __cplusplus的区别

你可能会想到另一个预定义宏 __cplusplus,它由编译器直接定义,用于指示编译器所遵循的 C++ 标准版本。

  • ​__cplusplus​:由 ​编译器​ 定义,表示编译器当前正在编译所遵循的 C++ 标准模式。它的值也是年份,例如 C++17 模式下其值通常为 201703L。
  • ​_LIBCPP_STD_VER​:由 ​libc++ 标准库头文件​ 定义,表示 ​libc++ 库本身实现所支持的最高或当前选择的 C++ 标准版本。

简单来说:

  • __cplusplus告诉你编译器在用什么模式。
  • _LIBCPP_STD_VER告诉你标准库在用什么模式。

在大多数正常配置下,_LIBCPP_STD_VER的值会和 __cplusplus的值保持一致(经过某种映射,例如 __cplusplus == 201703L时 _LIBCPP_STD_VER被定义为 17),因为它们需要协同工作。这个映射逻辑通常隐藏在 libc++ 的内部配置头文件(如 <__config>)中。

6、Mac中决定_LIBCPP_STD_VER 的地方
//代码2:
public CppStandardVersion CppStandard = CppStandardVersion.Default;
static string GetCppStandardCompileArgument(CppCompileEnvironment CompileEnvironment)
{var Mapping = new Dictionary<CppStandardVersion, string>{{ CppStandardVersion.Cpp14, " -std=c++14" },{ CppStandardVersion.Cpp17, " -std=c++17" },{ CppStandardVersion.Latest, " -std=c++17" },{ CppStandardVersion.Default, " -std=c++14" }};return Mapping[CompileEnvironment.CppStandard];
}

在我的构建机中,该默认配置,读取的就是c++14,也就是Mac机用的也就是c++14.

7、WINDOWS是否是 c++14 ?

是的,在我的构建机中,WINDOWS 也是c++14。论述如下。在UE4中,我看到下面变量决定了c++的标准:

public class ModuleRules 
{…… public CppStandardVersion CppStandard = CppStandardVersion.Default;……
}

然而在WINDOWS的构建机中,我观察到UBT产生的编译命令中,没有 -std=c++14 或 -std=c++17 或 /std:c++latest 或 /Qstd=c++14 或 /std:c++17 或 /std:c++14 中的任何一个。我调试的代码位于 UnrealBuildTool.VCToolChain.AppendCLArguments_CPP() ,UnrealBuildTool.VCToolChain里的 ​​"VC"​​ 字面上指的是 ​Visual C++​,这是微软(Microsoft)提供的 C++ 编译工具链 。最终观察到下面这些参数,它们记录在EngineSource\Engine\Intermediate\Build\Win64\UE4Editor\Development\Launch\Module.Launch.cpp.obj.response :

/Zc:inline

/nologo

/Oi

/c

/Gw

/Gy

/Zm1000

/wd4819

/D_CRT_STDIO_LEGACY_WIDE_SPECIFIERS=1

/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1

/D_DISABLE_EXTENDED_ALIGNED_STORAGE

/source-charset:utf-8

/execution-charset:utf-8

/Ox

/Ot

/GF

/Ob2

/errorReport:prompt

/EHsc

/Z7

/MD

/bigobj

/fp:fast

/Zo

/Zp8

/we4456

/we4458

/we4459

/wd4463

/wd4838

/we4668

也就是说,没有显式声明 C++版本。那么,WINDOWS下UE4最终会以什么C++标准来编译呢?

在 Windows 下观察到的 UE4 编译命令中没有显式指定 C++ 标准(如 /std:c++17),这通常意味着它依赖于编译器的默认标准。结合你提到的 ModuleRules中的 CppStandard = CppStandardVersion.Default设置,分析如下:

8、总结

在Mac构建机和WINDOWS构建机中,构建机编译器都正在用着C++14,而非C++17 。

前面我们知道,mac中 要用 C++17,才能编译到 is_void_v,但 为什么WINDOWS用 c++14 却也能编译 is_void_v ?

因为,在 WINDOWS的定义( C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.40.33807\include\type_traits )中,没有C++版本限制;

_EXPORT_STD template <class _Ty>
_INLINE_VAR constexpr bool is_void_v = is_same_v<remove_cv_t<_Ty>, void>;_EXPORT_STD template <class _Ty>
struct is_void : bool_constant<is_void_v<_Ty>> {};

而在 Mac的定义( /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/__type_traits/is_void.h )中,有C++版本限制;

#  if _LIBCPP_STD_VER >= 17
template <class _Tp>
inline constexpr bool is_void_v = __is_void(_Tp);
#  endif

修复方法

因此,我们将所有的 std::([^<]+)_v< 都替换为 std::($1)::value ,例如:

http://www.xdnf.cn/news/20351.html

相关文章:

  • 无需bootloader,BootROM -> Linux Kernel 启动模式
  • Java全栈开发工程师面试实录:从基础到实战的深度探讨
  • PyTorch图像数据转换为张量(Tensor)并进行归一化的标准操作
  • 管理中心理学问:动机与管理的关联
  • 什么是CRM?定义、作用、功能、选型|CRM百科
  • 使用若依加Trae快速搭建一对儿多对多CRUD
  • 移植Qt4.8.7到ARM40-A5
  • PiscCode基于 Mediapipe 实现轨迹跟踪
  • TOGAF之架构标准规范-迁移计划
  • nginx 反向代理使用变量的坑
  • 亚马逊商品转化率怎么提高?从传统运营到智能广告的系统化突破
  • Nginx 配置片段主要用于实现​​正向代理​​,可以用来转发 HTTP 和 HTTPS 请求
  • LangChain关于提示词的几种写法
  • 深度学习:Dropout 技术
  • c++ 第三方库与个人封装库
  • 【完整源码+数据集+部署教程】西兰花实例分割系统源码和数据集:改进yolo11-AggregatedAtt
  • leetcode 6 Z字形变化
  • 基于YOLOv8的车辆轨迹识别与目标检测研究分析软件源代码+详细文档
  • 整理了几道前端面试题
  • 字符串格式化——`vsnprintf`函数
  • 图像处理:实现多图点重叠效果
  • More Effective C++ 条款29:引用计数
  • 【完整源码+数据集+部署教程】骰子点数识别图像实例分割系统源码和数据集:改进yolo11-DCNV2
  • 【知识点讲解】模型扩展法则(Scaling Law)与计算最优模型全面解析:从入门到前沿
  • 深入了解synchronized
  • 2025世界职校技能大赛总决赛争夺赛汽车制造与维修赛道比赛资讯
  • 告别Qt Slider!用纯C++打造更轻量的TpSlider组件
  • 一文了解太阳光模拟器的汽车材料老化测试及标准解析
  • 企业级 AI Agent 开发指南:基于函数计算 FC Sandbox 方案实现类 Chat Coding AI Agent
  • 集成学习 | MATLAB基于CNN-LSTM-Adaboost多输入单输出回归预测