具有共享所有者语义的容器
Container with shared owner semantics
我正在设计带有共享所有权语义的容器类型。它支持切片,因此将切片共享所有权。我的问题之一是数据共享似乎干扰了const正确性,因此我试图注意这一点,但我对结果不满意。
以下是我实际代码的大量细分版本:
#include <memory>
#include <vector>
#include <algorithm>
template <typename T>
class SharedMem
{
public:
SharedMem(std::initializer_list<T> init)
: m_mem(std::make_shared<std::vector<T>>(init.begin(), init.end()))
, m_data(m_mem->data())
, m_size(m_mem->size())
{ }
SharedMem(SharedMem& other) = default; // best-effort for copy-construction
SharedMem(SharedMem const& other) = delete; // disallow, would circumvent const-correctness
SharedMem& operator = (SharedMem const& other) {
std::copy(other.m_data, other.m_data + other.m_size, m_data);
return *this;
}
std::size_t size() const
{ return m_size; }
T& operator [] (std::size_t index)
{ return m_data[index]; }
T const& operator [] (std::size_t index) const
{ return m_data[index]; }
SharedMem slice(std::size_t first, std::size_t last) {
SharedMem<T> ret(*this);
ret.m_data += first;
ret.m_size = last - first;
return ret;
}
SharedMem const slice(std::size_t first, std::size_t last) const {
SharedMem<T> ret(*this);
ret.m_data += first;
ret.m_size = last - first;
return ret;
}
private:
std::shared_ptr<std::vector<T>> m_mem; // shared underlying memory
T* m_data; // start of slice
std::size_t m_size; // size of slice
};
预期用途:
int main(int argc, char** argv) {
SharedMem<int> a { 0, 1, 2, 3, 4 };
SharedMem<int> b { 8, 9 };
SharedMem<int> c = a; // shallow copy of a, data is shared
a.slice(1, 3) = b; // a = [0, 8, 9, 3, 4]
c[4] = 6; // a = [0, 8, 9, 3, 6]
}
有些事告诉我我在错误的轨道上。我看到了我的方法以下问题:
- 它违反了3的规则。我特别不喜欢为固定const-recrectness禁用默认复制构造函数。否则,可以创建const对象的非符合副本,后者可以修改前者的元素。
- 复制构造和分配实施截然不同的操作。这就是我使
c = a
和a.slice(1, 3) = b
做正确的事情(实际上是非常不同的事情)的方式。
我不确定我是否遇到麻烦。问题:
- 这种设计还可以还是会引起问题?如果是这样,哪个?
- 如果存在严重缺陷,如何解决/避免?
感谢您的任何提示。
您需要分开类型,以正确的方式正确地完成此工作。由于您发现的非常相似的原因,对于所有标准库容器,iterator
和const_iterator
都是不同的类型。
也就您的用例)。
如果您想尝试一下,一个解决方案可以看起来像这样:
namespace detail
{
template<class T, bool Const>
struct SharedInternalsT;
template<class T>
struct SharedInternalsT<T, true>
{
const T * m_data;
std::size_t m_size;
};
template<class T>
struct SharedInternalsT<T, false>
{
T * m_data;
std::size_t m_size;
};
template<class T>
using SharedInternals = SharedInternals<T, false>;
template<class T>
using ConstSharedInternals = SharedInternals<T, true>;
}
template<class T, bool Const>
class SharedMemT
{
public:
using Traits = SharedMemTraits<T, Const>;
using Ptr = typename Traits::Ptr;
//now we can safely copy in a const correct way.
SharedMemT(const SharedMemT & _other) :
m_mem(_other.m_mem),
m_internals(_other.m_internals)
{
}
private:
std::shared_ptr<std::vector<T>> m_mem;
detail::SharedInternals<T, Const> m_internals;
};
template<class T>
using SharedMem = SharedMemT<T, false>;
template<class T>
using ConstSharedMem = SharedMemT<T, true>;
这将是迈向解决方案的第一步。您很可能必须引入更多的间接性,以便能够从非const版本正确构建漫画(可能是通过使用std::enable_if
等启用/禁用某些模板复制构造函数等)。正如我所说,只有在您构建某种标准库的代码件时,我才会走这条路线。如果您只是为游戏或类似的东西建造一个小型实用程序,请忽略const正确性,不要浪费时间。
相关文章:
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- Boost Spirit,获取迭代器内部语义动作
- 可以使用移动语义更改或改进此C++代码吗?
- c++在使用指针时移动语义
- 在C++17中,引用const字符串的语义应该是什么
- Xcode 语义问题引用或以前定义的代码
- C++ 警告:将新创建的 gsl::owner<> 分配给非所有者
- 堆分配的对象是否存在永不为空的唯一所有者?
- 使用移动和复制语义时函数匹配如何工作?
- 将向量从 N1 缩小到 N2 项,而不触发默认构造函数并仅使用 move 语义
- 移动语义和深层/浅层复制之间有什么关系?
- 了解构造函数在移动、复制、赋值语义中的行为
- std::unique_lock移动语义
- 移动语义和运算符 + 重载
- C++ 移动语义是否在任何情况下都能节省资源?
- 移动语义在这里如何工作?
- 允许多个互斥锁所有者或指定数量的并发代码执行
- 使用移动语义:右值引用作为方法参数
- 具有共享所有者语义的容器