如何在模板中存储左值或右值引用
How to store either rvalue or lvalue references in template
我试图创建一个简单的模板enumerator
类,它应该接受定义:
操作符的任何对象,后来打印对形式(i, v[i])
。一个简单的实现如下:
template<typename T>
struct enumerator {
T &v; // reference to minimize copying
enumerator(T &_v) : v(_v) {}
void do_enumerate() {
size_t i = 0;
for(auto x : v) {
cout << i << x << endl;
i++;
}
}
};
情况下
vector<int> v({1,2,6,2,4});
auto e = enumerator(v);
e.do_enumerate();
然而,我也希望它处理临时对象,如:
案例B
auto e = enumerator(vector<int>({2,3,9});
e.do_enumerate();
这不起作用,编译器会抛出:
no matching function for call to ‘enumerator<std::vector<int> >::enumerator(std::vector<int>)
所以,我试着添加一个
enumerator(T _t) : t(_T) {}
构造函数来解决此错误。现在情况A不工作,有一个错误:
error: call of overloaded ‘enumerator(std::vector<int>&)’ is ambiguous
而且,在情形B中,枚举的输出是不正确的。
解决这个问题最干净的方法是什么?I would
- 真的希望这两种情况都能正常工作
- 建议不要使用stdc++以外的库
- 希望尽可能少的复制(因此只是在结构体中存储
T t
不是一个选项) - c++ 11不是问题。我有c++ -4.8,我认为它已经完全支持c++ 11了。
如果参数是右值,我想复制,如果不是右值,就不复制。这可能吗?
这可以使用make_enumerator
帮助函数完成,如下所示。
template <class T>
struct enumerator {
T v;
enumerator(T&& _v) : v(std::forward<T>(_v)) {}
void do_enumerate() {
size_t i = 0;
for(auto x : v) {
cout << i << x << endl;
i++;
}
}
};
template <class T>
enumerator<T> make_enumerator(T&& x) {
return enumerator<T>(std::forward<T>(x));
}
int main() {
vector<int> v {5, 2, 9, 1};
make_enumerator(v).do_enumerate();
make_enumerator(std::move(v)).do_enumerate();
}
这是如何工作的?
如果make_enumerator
的实参是A
类型的左值,则T
被演绎为A&
,得到枚举数enumerator<A&>
;如果A
类型的右值,则T
被演绎为A
,得到枚举数enumerator<A>
。
在第一种情况下,成员enumerator::v
将具有类型A&
,这是绑定到构造函数实参的左值引用(没有复制)。在第二种情况下,成员的类型为A
。使用std::forward
将参数_v
强制转换为右值,因此它将从初始化v
时开始移动。
这是一个经典的例子,你实际上不需要class
/struct
(实际上引入了无用的代码),你可以使用好的旧函数:
template<typename Container>
void enumerate(const Container& t) {
std::size_t i = 0;
for(auto it = t.begin(); it != t.end(); ++it, ++i)
std::cout << i << *it << std::endl;
}
,然后调用为:
enumerate(std::vector<int>{2,3,9});
现场演示
使用此方法,您还可以免费获得参数类型推断(这是struct
无法获得的)。
相关文章:
- 在函数内创建的对象的范围 - 如果在函数外部存储和访问引用,它们是否有效?
- 存储对(可能)临时对象的引用是否合法,只要引用不比对象存活?
- 在C++中,如果成员引用在其声明中初始化,为什么需要存储空间?
- 我们如何在指针中存储对对象的引用?
- 如何在拥有的C++对象中安全地存储对所有者的引用?
- C++ 在节点内存储对数据对象的引用,而不复制数据
- 标准库容器结构是否存储副本或引用?
- 如果结果存储在变量中forward_as_tuple然后在 std::apply 中使用之前丢失右值引用
- 是否可以将引用存储在标准::任何中
- 在模板中存储右值引用的危险
- 通过引用传递对象并将其存储为成员变量
- 每当传递lvalue时,每当通过rvalue传递时,将const引用存储
- 按名称存储和引用变量列表
- 在类中存储引用
- 我应该将引用存储在c++中的类中吗
- c++将对纯虚拟类的引用存储为类的成员
- 将对象引用存储在一个简单的容器中
- 您可以使用 boost::reference_wrapper 将引用存储在 STL 容器中吗?
- 我可以在不产生引用存储成本的情况下对变量进行别名吗
- 如何将对象作为引用存储在数组、列表或映射中