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
相关产品推荐
相关产品推荐

