提问人:SherAndrei 提问时间:6/17/2023 最后编辑:SherAndrei 更新时间:6/18/2023 访问量:145
具有可变成员的“std::p air”的类似物?
Analogue of `std::pair` with mutable members?
问:
我正在实现基于 的调用的类似物。想法很简单:当有新的插入物时,将检查过期的元素,如果存在,则将其删除。std::map
expiring_map
boost::multi_index::multi_index_container
expiring_map
我想有一些类似的接口:std::map
template <class Clock, class Key, class T, class Compare = std::less<Key>>
class expiring_map
{
explicit expiring_map(clock_type cl, duration expiry_duration);
void insert_or_assign(value_type v);
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
// size(), clear() and lookup-methods are omitted for simplicity
};
我还希望下一个代码有效
auto clock = std::make_shared<std::chrono::steady_clock>();
expiring_map<decltype(clock), int, std::string> m{ clock, std::chrono::seconds{ 1 } };
m.insert_or_assign({ 1, "value" });
const auto b = m.begin();
auto v = std::move(b->second);
EXPECT_EQ(v, "value");
EXPECT_TRUE(b->second.empty());
由于索引的所有元素都被认为是不可变的,因此(根据此答案)我达到所需结果的唯一方法是指定下一个结构boost::multi_index::multi_index_container
value_type
expiring_map
struct value_type {
const Key first;
mutable T second;
};
因为 c++ 表达式无效,因为关键字是关于存储持续时间的,而不是关于类型的。从 https://en.cppreference.com/w/cpp/language/cvusing value_type = std::pair<const Key, mutable T>
mutable
C++ 语言语法将可变视为存储类说明符,而不是类型限定符,但它不会影响存储类或链接。
问题
我对这个解决方案的问题是我的重载,而不是真正的常量,下一个代码正在编译:const
begin()
end()
using subject_type = ::expiring_map<std::shared_ptr<std::chrono::steady_clock>, int, std::string>;
void foo(const subject_type& s) {
s.begin()->second = "new";
}
我怎样才能改变我的实现,以实现const重载,并实现编译错误,但保留这些方法(以便仍然能够使用基于范围的迭代)?begin()
end()
const expiring_map&
链接到 godbolt 与当前实现和测试
我试过什么
我尝试使用不同的提取器,例如
struct extract_value_type_as_const_ref {
[[nodiscard]] std::pair<const Key&, const T&> operator()(const node_type& n) const { return { n.second.first, n.second.second }; }
};
using const_iterator = decltype(boost::make_transform_iterator<extract_value_type_as_const_ref>(std::declval<underlying_type>().template get<by_value_type>().cbegin()));
但需要 for result of 可转换为,但我真的不想复制我的所有构造函数::testing::ElementsAre
*(map.begin())
value_type
std::pair
value_type
答:
您的成员不应是 .这是修复:second
value_type
mutable
struct value_type {
const Key first;
T second;
};
进行此更改将使您在编译器资源管理器上的断言通过。
也许你对地图的总体误解了。
A 将存储 .value_type
std::map<Key, Value>
value_type = std::pair<const Key, Value>
- 必须是 .否则,我们将能够在不改变映射中对的位置的情况下更改键,这会破坏数据结构。
Key
const
- 不可
变
。A 将暴露 ,并且存储在该对中的 也是 。1)Value
const std::map
const value_type&
Value
const
此外,它不会编译是有道理的。 是数据成员(如 OR)的属性,它不是 A 类型的一部分。std::pair<const Key, mutable T>
mutable
private
static
通常,仅用于在所有情况下都必须可变的数据成员,即使在对象内部也是如此。例如,成员通常是可变的,因为 a 不可用,无论如何您都需要能够使用它。mutable
const
std::mutex
const std::mutex
1)里面存储的可能不是一个对象,而是一个可变的对象。从技术上讲,你仍然可以在那时候改变它。但是,这不能依赖。Value
const
const_cast
评论
mutable
mutable
仅用于在所有情况下都必须可变的数据成员,是的,我知道,但我想找到一种方法来修改元素,仅使用我的迭代器,而无需辅助方法,例如boost::multi_index::multi_index_container
modify
replace
boost
评论
brew install googletest
clang++ -std=c++17 -lgtest -lgmock a.cpp
const_iterator begin() const = delete;
::testing::ElementsAre
::testing::ElementsAre
auto v = std::move(b->second);
没有意义。 是 ,而不是指针。b
std::string
value_type
T& mut_second() const { auto& self = const_cast<value_type&>(*this); return self.second; }
second
mutable