接受左值和右值参数的函数

有没有办法在C ++中编写一个接受左值和右值参数的函数,而不必将其作为模板?

例如,假设我编写了一个函数print_stream ,它从istream中读取并打印读取到屏幕上的数据,或者其他东西。

我认为这样调用print_stream是合理的:

fstream file{"filename"};
print_stream(file);

以及像这样:

print_stream(fstream{"filename"});

但是,我该如何声明print_stream以使两个使用都有效?

如果我声明为

void print_stream(istream& is);

那么第二次使用将不会编译,因为右值不会绑定到非常量左值引用。

如果我声明为

void print_stream(istream&& is);

那么第一次使用将不会编译,因为左值不会绑定到右值引用。

如果我声明为

void print_stream(const istream& is);

那么该函数的实现将不会编译,因为您无法从const istream读取。

我不能将该函数作为模板并使用“通用引用”,因为它的实现需要单独编译。

我可以提供两个重载:

void print_stream(istream& is);
void print_stream(istream&& is);

并且第二次调用第一次,但是这看起来像是大量不必要的样板文件,并且每次我用这样的语义编写函数时都必须这样做,这是非常不幸的。

我能做些更好的事情吗?


除了提供两个重载或将你的函数作为模板之外,没有太多的理智选择,我会说。

如果你确实需要一个(丑陋的)选择,那么我认为你能做的唯一(疯狂的)事情就是让你的函数接受一个const& ,前提条件是你不能传递一个const限定的对象键入它(反正你不想支持)。 然后该函数可以抛弃引用的const

但是我亲自编写了两个重载并用另一个来定义一个重载,所以你重复声明,但不是定义:

void foo(X& x) 
{ 
    // Here goes the stuff... 
}

void foo(X&& x) { foo(x); }

另一个相当丑陋的选择是将函数作为模板并明确实例化两个版本:

template<typename T>
void print(T&&) { /* ... */ }

template void print<istream&>(istream&);
template void print<istream&&>(istream&&);

这可以单独编译。 客户端代码只需要模板的声明。

不过,我个人只是坚持Andy Prowl的建议。


// Because of universal reference
// template function with && can catch rvalue and lvalue 
// We can use std::is_same to restrict T must be istream
// it's an alternative choice, and i think is's better than two overload functions
template <typename T>
typename std::enable_if<
  std::is_same<typename std::decay<T>::type, istream>::value
>::type
print(T&& t) {
  // you can get the real value type by forward
  // std::forward<T>(t)
}
链接地址: http://www.djcxy.com/p/40293.html

上一篇: Function that accepts both lvalue and rvalue arguments

下一篇: Exact difference between rvalue and lvalue