假设我希望函数foo
将左值或右值引用作为参数。
我可以通过左值和左值引用将其分解为两个重载。
void foo(int& a){/*some impl*/} // lvalue ref
void foo(int&& a){foo(a);} // rvalue ref
int main(){
int a;
foo(a); // lvalue
foo(1); // rvalue
}
它确实有效,但非常冗长。我可以使用模板来改进它。
template<typename T>
void foo(T &&a) { /*some impl*/ }
int main(){
int a;
foo(a); // lvalue, T = int&
foo(1); // rvalue, T = int
}
对于二元函数,模板需要采用两个模板参数。
template<typename T1, typename T2>
void foo(T1 &&a, T2 &&b) { /*some impl*/ }
int main(){
int a;
foo(a, a); // (lvalue, lvalue), T1 = int&, T2 = int&
foo(1, 1); // (rvalue, rvalue), T1 = int, T2 = int
foo(1, a); // (rvalue, lvalue), T1 = int, T2 = int&
foo(a, 1); // (lvalue, rvalue), T1 = int&, T2 = int
}
这是要走的路吗?还有更好的办法吗?
我几乎没有任何使用cpp的经验,但似乎很可疑我需要做这样的技巧来简单地说“不要复制传递的参数”。
我将gcc 5.4.0
与-std=c++11
一起使用。
- 更新1 -
当我使用streams库range(T&& lower, T&& upper)
方法获取两个T&&
参数时,我想出了这个问题。我可以将lvalue
或rvalue
参数传递给函数,但这使我无法传递示例0
和some_var
作为参数。无论作者采用T&&
参数的函数的原因是什么,我想知道是否有办法扩展声明以采用混合左值/右值参数而不牺牲作者想要实现的任何目的。
- 更新2 -
如果参数是只读的const &
可以使用(@RichardCritten)。
如果您想在不复制的情况下修改/返回参数,可以使用模板或@Yakk解决方案。
当你声明一个带有多个参数的函数时,@Yakk解决方案似乎更好。
例如,如果一个函数接受两个int l / r-value引用参数并使用模板返回int引用会导致一个混乱的签名。
template<typename T1, typename T2>
int& foo(T1 &&a, T2 &&b) {
a += b;
return a;
}
虽然@Yakk解决方案非常优雅。
int& foo(any_ref<int> a, any_ref<int> b) {
a += b;
return a;
}
答案 0 :(得分:1)
template<class T>
struct any_ref{
T& t;
any_ref(T&in):t(in){}
any_ref(T&&in):any_ref(in){}
any_ref(any_ref const&)=default;
any_ref& operator=(any_ref const&)=default;
~any_ref()=default;
operator T&()const&{return t;}
operator T&&()&&{return std::move(t);}// maybe
T& get()const{return *this;}
};
然后:
void foo(any_ref<int>a, any_ref<int>b);
不是模板功能。如果想要真正的参考,身体可以做int&a=a_arg;
。
但实际上,如果你想要一个&#34;可能出来&#34;那么就去int&
。参数。想要将右值作为左值传递的调用者可以写:
templare<class T>
T& as_lvalue(T&&t){return t;}
并抛弃他们的左撇子。
如果参数是只读参考,请使用const&
。