接受左值和右值参数的函数
有没有办法在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