我想编写一些函数,这些函数将Object作为它们的参数之一,无论是通过lvalue还是rvalue,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)。
是否有更好的方法来解决这个问题,还是我对其中任何一个感觉不太好?
发布于 2014-10-28 14:36:47
接受lvalue和rvalue的典型方法是创建一个接受const引用的函数。这意味着您不能在对象上调用非const函数,但是如果您想传递rvalue(比如临时的),那么调用非const函数就没有什么必要了。
发布于 2014-10-28 14:40:35
两种实现之间存在差异。第一个将承认任何可转换为Object、Object&&或Object&的东西。第二种只承认Object和以rvalue或lvalue形式继承的东西(并拒绝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; }在需要时将rvalue转换为lvalue(您也可以称其为unmove,以使其可爱)
https://stackoverflow.com/questions/26610906
复制相似问题