声明可以采用右值或左值引用的函数的正确方法是什么?

时间:2017-02-06 01:46:58

标签: c++ c++11

假设我希望函数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 -

当我使用streamsrange(T&& lower, T&& upper)方法获取两个T&&参数时,我想出了这个问题。我可以将lvaluervalue参数传递给函数,但这使我无法传递示例0some_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;
}

1 个答案:

答案 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&