前段时间我遇到了一些用mutable关键字标记类的成员变量的代码.据我所知,它只是允许您修改const方法中的变量:
class Foo
{
private:
mutable bool done_;
public:
void doSomething() const { ...; done_ = true; }
};
Run Code Online (Sandbox Code Playgroud)
这是这个关键字的唯一用途,还是有更多的东西比它的眼睛?我已经在一个类中使用了这个技术,标记为一个boost::mutex可变的允许const函数为了线程安全的原因锁定它,但是,说实话,这感觉有点像黑客.
在C++ 14中,关联容器似乎已从C++ 11改变 - [associative.reqmts]/13说:
成员函数模板
find,count,lower_bound,upper_bound,并且equal_range不得,除非类型参与重载决议Compare::is_transparent存在.
使比较器"透明"的目的是什么?
C++ 14还提供了这样的库模板:
template <class T = void> struct less {
constexpr bool operator()(const T& x, const T& y) const;
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
template <> struct less<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
typedef *unspecified* is_transparent;
};
Run Code Online (Sandbox Code Playgroud)
因此,例如,std::set<T, std::less<T>>将不会有一个透明的比较,而是std::set<T, std::less<>> …
我创建了一个简单的双向映射类,它通过内部存储两个std::map具有相反键/值类型的实例,并提供用户友好的界面:
template<class T1, class T2> class Bimap
{
std::map<T1, T2> map1;
std::map<T2, T1> map2;
// ...
};
Run Code Online (Sandbox Code Playgroud)
是否有更有效的方法来实现不需要两倍内存的双向映射?
通常如何实施bimap?
编辑:
bimap元素应该是可变的还是不可变的?(更改一个元素map1应该更改键map2,但键是常量,这是不可能的 - 解决方案是什么?)
元素的所有权也是另一个问题:当用户在bimap中插入键值对时,bimap应该复制该键值对并存储它,然后内部第二个映射(具有反转的键/值)应该不复制,但指向原始对.怎么能实现这一目标?
编辑2:
我经常发现自己想写这样的代码:
class MyClass
{
public:
void addObject(std::unique_ptr<Object>&& newObject);
void removeObject(const Object* target);
private:
std::set<std::unique_ptr<Object>> objects;
};
Run Code Online (Sandbox Code Playgroud)
但是,很多std :: set接口对std :: unique_ptrs都没用,因为查找函数需要std :: unique_ptr参数(我显然没有这些参数,因为它们由集合本身拥有).
我可以想到两个主要的解决方案.
创建临时unique_ptr以进行查找.例如,上面的removeObject()可以实现如下:
void MyClass::removeObject(const Object* target)
{
std::unique_ptr<Object> targetSmartPtr(target);
objects.erase(targetSmartPtr);
targetSmartPtr.release();
}
Run Code Online (Sandbox Code Playgroud)将原始指针映射替换为unique_ptrs.
// ...
std::map<const Object*, std::unique_ptr<Object>> objects;
};
Run Code Online (Sandbox Code Playgroud)然而,对我来说,两者似乎都有点愚蠢.在解决方案1中,erase()不是noexcept,因此临时unique_ptr可能会删除它实际上不拥有的对象,而2需要不必要地为容器存储两倍.
我知道Boost的指针容器,但与现代C++ 11标准库容器相比,它们目前的功能有限.
我最近在阅读有关C++ 14的内容,并且遇到了"将异构比较查找添加到关联容器".但是形成我对它的理解,查找类型必须与键类型相当,但原始指针不能与unique_ptrs相比.
任何人都知道更优雅的解决方案或即将添加的C++解决了这个问题?
我遇到了一个记录存储为的要求
Name : Employee_Id : Address
Run Code Online (Sandbox Code Playgroud)
其中Name和Employee_Id应该是键,在Name和Employee Id上都提供搜索功能.
我可以考虑使用地图来存储这个结构
std::map< std:pair<std::string,std::string> , std::string >
// < < Name , Employee-Id> , Address >
Run Code Online (Sandbox Code Playgroud)
但我不确定搜索功能的样子.
据我所知,我的STL(g ++ 4.xx附带)使用红黑树来实现地图等容器.是否可以直接使用STL的内部红黑树.如果是这样,怎么样?如果没有,为什么不 - 为什么STL不暴露红黑树?
令人惊讶的是,我无法使用谷歌找到答案.
编辑:我正在调查使用红黑树作为插入时额外的allocator构造函数调用的解决方案.看到这个问题.我的STL使用红黑树来实现地图.
假设我有以下内容:
struct MetadataThingy {
void *actual_thingy;
int some_metadata;
int more_metadata;
bool operator<(MetadataThingy const& other) const {
return actual_thingy < other.actual_thingy;
}
};
Run Code Online (Sandbox Code Playgroud)
其中actual_thingy指向一些重要数据,我希望容器按值actual_thingy而不是指向的元素的值排序,但是我需要存储一些关于它的其他数据,所以我MetadataThingy用一个只考虑的比较器创建了包装类actual_thingy指针的值(而不是使用容器void *)
现在,给出以下代码:
std::set<MetadataThingy> thingy_set;
void test() {
MetadataThingy m1 { nullptr, 5, 20 };
MetadataThingy m2 { &m1, 1, 2 };
MetadataThingy m3 { &m2, 6, 0 };
thingy_set.insert(m1);
thingy_set.insert(m2);
thingy_set.insert(m3);
MetadataThingy m;
m = *thingy_set.find(m2); // OK.
m = *thingy_set.find(static_cast<void *>(&m2)); // Nope. Can't use a …Run Code Online (Sandbox Code Playgroud)