接受左值引用或右值引用
Accept lvalue ref or rvalue ref
本文关键字:引用 更新时间:2023-10-16
我想写一些函数,将Object
作为它们的参数之一,无论是通过左值还是右值ref都无关紧要,但绝对不是通过值,绝对只有Object
。我似乎有两个选择:
void foo(Object& o) {
// stuff
}
void foo(Object&& o) { foo(o); } // this is fine for my use-case
或者使用通用参考:
template <typename T, typename U>
using decays_to = typename std::is_same<std::decay_t<T>, U>::type;
template <typename T>
std::enable_if_t<decays_to<T, Object>::value>
foo(T&& o)
{
// same stuff as before
}
但第一个选项涉及编写两倍于我需要的函数,第二个选项涉及写一堆模板,这对我来说似乎有些过头了(我有点把它读成接受o
的任何——哦,开玩笑,真的只是一个Object
)。
有没有更好的方法来解决这个问题,或者我只是被其中任何一个我感觉不太好的方法卡住了?
您的两个实现之间存在差异。第一个将允许任何可转换为Object
、Object&&
或Object&
的内容。第二个只允许Object
和以右值或左值形式继承的东西(并拒绝const Object
,就像第一个一样)。
我们可以添加一个辅助对象:
template<class T>
struct l_or_r_value {
T& t;
l_or_r_value( T&& t_ ):t(t_) {}
l_or_r_value( T& t_ ):t(t_) {}
operator T&(){ return t; }
T* operator->(){ return &t; }
T& operator*(){ return t; }
T& get(){ return t; }
};
然后我们可以写:
void foo(l_or_r_value<Object> o)
我们得到的行为与您的第二个解决方案非常接近,在调用点没有模板繁琐。您必须访问*o
和o->
或执行Object& o = o_;
才能获得原始引用。
它与第一个解决方案不同,因为C++不链接两个用户定义的转换。
概念提案将增加用更简洁的语法说"我接受这里的任何东西,只要它是Object
"的能力。
另一种方法是只采用Object&
,并使用:
tepmlate<class T>
T& lvalue( T&& t) { return t; }
在需要时将右值转换为左值(为了可爱,也可以称之为unmove
)
同时接受左值和右值的典型方法是生成一个使用常量引用的函数。这意味着你不能在对象上调用非常量函数,但如果你想传递右值,比如临时值,那么调用非常量的函数就没有多大意义了。
相关文章:
- 将对象数组的引用传递给函数
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 何时在引用或唯一指针上使用移动语义
- 如何在c++中使用引用实现类似python的行为
- 编译C++时未定义的引用
- Ctypes wstring通过引用传递
- c++r值引用应用于函数指针
- 理解c++中的引用
- C++取消引用指针.为什么会发生变化
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 强制转换为引用类型
- 引用一个已擦除类型(void*)的指针
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 具有默认值的引用获取函数
- 如何使用基类指针引用派生类成员
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 如何引用基类的派生类?