std::forward_like 并非 C++23 标准函数,未被 ISO/IEC 14882:2024 收录,编译器会报错;它源于未标准化的 P2569R1 提案,实际应使用 std::forward + decltype 或 std::forward_as_tuple 等现有机制。

std::forward_like 不存在,C++23 没有这个标准函数
直接说结论:std::forward_like 并不是 C++23 引入的合法标准库设施。你查不到它的声明,编译器会报 error: 'forward_like' is not a member of 'std'。它既不在 <utility></utility> 里,也没出现在 ISO/IEC 14882:2024(C++23)最终草案中。网上零星出现的讨论,多源于早期提案(如 P2569R1)的误传或实验性实现(比如某些 libc++ 的私有分支),但未被标准化。
真正可用的是 std::forward_as_tuple + std::tuple_cat 组合,或手动写转发逻辑
如果你的目标是“把一个对象以和原类型相同的值类别(lvalue/rvalue)转发给另一个类型”,C++23 仍需靠现有工具组合实现。常见场景是:封装一个 T 类型的对象,再将其“像 T 那样”转发给内部存储或构造函数。
-
std::forward_as_tuple能保留每个实参的值类别,适合多参数转发; - 对单个对象,最稳妥做法仍是用
decltype+std::forward显式推导源表达式的类型:
template<typename T>
struct wrapper {
T value;
template<typename U>
wrapper(U&& u) : value(std::forward<U>(u)) {}
// 想“像 T 那样”转发 value?只能靠 decltype:
template<typename U>
auto&& forward_as_T(U&& u) {
return std::forward<decltype(u)>(u); // 注意:这里 forward 的是 u,不是 value
}
};
若真要转发 value 本身(即按 value 当前绑定类型转发),就得看它是 lvalue 还是 rvalue —— 这通常意味着你需要在构造时记录原始类别,或改用引用成员。
为什么有人会误以为有 std::forward_like?
混淆主要来自三方面:
立即学习“C++免费学习笔记(深入)”;
- P2569R1 提案(“A Design for
std::forward_like”)确实在 2022 年被提出,目标是提供template<typename t typename u> constexpr U&& forward_like(T&& t) noexcept;</typename>,但它在 C++23 标准化流程中**未进入 TS 或正式标准**; - 部分编译器(如较新版本的 Clang + libc++ 实验配置)可能启用了该提案的预览实现,但属于非标准扩展,不可移植;
- 名字和
std::move/std::forward太像,容易让人默认“既然有 forward,那 forward_like 应该也有了”。
实际项目中该怎么做?
别依赖不存在的 std::forward_like。遇到需要模拟类似行为的场景,优先考虑:
- 用
std::forward<t>(x)</t>+ 明确的模板参数,这是最可控、最通用的方式; - 如果封装的是可移动/可拷贝对象,且调用方能控制传入方式,就让接口接收
T&&并直接转发; - 避免在运行时“猜测”值类别 —— C++ 的转发必须基于编译期类型信息,
decltype(x)和表达式值类别(lvalue/rvalue)才是唯一可靠依据; - 真需要跨类型“模仿转发”,比如把
int&转发为const int&,那就得手写static_cast或重载,因为std::forward不处理 cv-qualifier 传导。
最容易被忽略的一点:所谓“像某个类型那样转发”,本质是转发**表达式本身的值类别和 cv 限定符**,而不是“让目标类型获得相同行为”。后者往往需要设计层面的重构,而非一个神奇函数。


















