You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

enable_if是否为定义接受任意类型右值函数的最简洁方式?

仅接受右值参数的C++函数实现方案

你原有基于转发引用+默认模板参数SFINAE的实现是正确的,确实可以做到仅允许右值传入,存在更简洁的写法,以下分场景说明:

C++17可用的更短实现

你原写法需要额外定义一个用于SFINAE约束的默认模板参数,可以直接将约束放到后置返回值位置,减少模板参数声明,代码更短,效果完全一致:

#include <utility>
template<typename T>
auto f(T&&) -> std::enable_if_t<std::is_rvalue_reference_v<T&&>> {}

该实现的逻辑和你原代码完全相同:

  • 传入右值(std::move(i)、临时对象int{1})时,模板参数T被推导为非引用类型,T&&为右值引用,std::is_rvalue_reference_v判定为真,SFINAE约束通过,编译正常
  • 传入左值(普通变量i、const左值等)时,模板参数T被推导为左值引用类型,T&&折叠为左值引用,std::is_rvalue_reference_v判定为假,SFINAE约束失败,触发编译错误

注:std::is_rvalue_reference_v<T&&>可以替换为!std::is_lvalue_reference_v<T>,二者在转发引用的推导场景下完全等价,代码长度相近。

你也可以通过删除左值重载的方式实现,但需要同时删除非const左值引用和const左值引用两个重载,代码量比上述SFINAE写法更长,且重载决议规则更容易踩坑,不推荐使用。

你尝试的decltype写法失效原因

你写的如下写法确实无法生效:

template<typename T>
auto f(decltype(std::declval<T>())&&) {}

正如你查阅文档得到的结论,decltype说明符内的表达式属于非推导上下文,编译器无法通过传入的实参反向推导模板参数T的类型,除非手动显式指定模板参数(如f<int>(std::move(i))),完全失去了模板自动推导的便利性,因此没有实用价值。

C++20更简洁的写法(扩展参考)

如果可以使用C++20标准,用概念约束可以写出更直观的短实现:

#include <utility>
template<typename T>
requires std::is_rvalue_reference_v<T&&>
auto f(T&&) {}

内容的提问来源于stack exchange,提问作者Enlico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 08:24:21