c++ - 如何正确实现 -> 和 (*)。使它们的行为类似于 -> 和 (*)。在迭代器中
问题描述
我想为定制容器的迭代器实现 * 和 -> 运算符。我的代码无法编译。下面是一个“最小的非工作示例”,它显示了它如何与 std::map 一起工作,但不在我的代码中。
#include <vector>
#include <map>
#include <iostream>
struct thing {
float f[1];
typedef std::pair<int,float> key_data;
struct iterator {
int pos;
const float *f;
key_data operator*() const { return key_data(pos,f[pos]); }
key_data *operator->() const { return &key_data(pos,f[pos]); }
};
iterator begin() const { return {.f = f, .pos = 0}; }
};
template<typename T> void test(T iter) {
(*iter).second = 1.0; std::cout << (*iter).second;
iter->second = 2.0; std::cout << iter->second;
}
int main() {
std::map<int,float> fmap; fmap[0] = 0.0;
test(fmap.begin());
std::cout << fmap[0];
thing f;
test(f.begin());
std::cout << f.f[0];
}
我希望它能够编译:),然后打印122122
。编译时的错误消息是:
access.cc:13:43: error: taking the address of a temporary object of type 'key_data'
(aka 'pair<int, float>') [-Waddress-of-temporary]
key_data *operator->() const { return &key_data(pos,f[pos]); }
access.cc:20:18: error: expression is not assignable
(*iter).second = 1.0; std::cout << (*iter).second;
对于第一个:足够公平, std::pair<> 创建一个不能通过引用返回的临时对象;但是标准库如何做到这一点以允许通常的 -> 语法?
第二个:可能我再次尝试分配一个临时的,但我无法猜测正确的语法是什么。
解决方案
更简单的是在迭代器中有直接正确的类型:
struct thing {
float f[1];
using key_data = std::pair<int,float&>;
struct iterator {
key_data data;
const key_data& operator*() { return data; }
key_data *operator->() { return &data; }
};
iterator begin() { return {{0, f[0] }}; }
};
另一种解决方案是使用包装器,例如:
struct pair_wrapper
{
int &first;
float& second;
pair_wrapper* operator->() { return this; }
};
struct thing {
float f[1];
typedef std::pair<int,float> key_data;
struct iterator {
int pos;
float *f;
pair_wrapper operator*() { return pair_wrapper{pos,f[pos]}; }
pair_wrapper operator->() { return pair_wrapper{pos,f[pos]}; }
};
iterator begin() { return {0, f}; }
};
它使用operator->
.
推荐阅读
- java - Mockito:预期 0 个匹配器,记录 1 个
- django - Django - 如何导入 python 模块?
- exception - 从 orElseGet 中抛出的异常被 UndeclaredThrowableException 包裹
- entity-framework-core - 更新在 Asp.net Core MVC 项目中创建的迁移时出错 - Equinox
- java - 如何安全地为 Camel JDBC 组件生成 SQL
- reactjs - 你能从 React 中的函数渲染一个 div 吗?
- ruby-on-rails - 如何为 Rails 迁移中的列编写本机枚举类型?
- php - 如何将课程添加到最后
- 在 Wordpress 导航栏中?
- sql - 我们有年龄列,因为我们有单个值或 15+ 值,我们需要有单个值或 15+
- compiler-errors - Biblatex 无法在 bibliography.bib 中找到参考文献