gpt4 book ai didi

c++ - 具有共享所有者语义的容器

转载 作者:行者123 更新时间:2023-11-28 01:52:25 24 4
gpt4 key购买 nike

我正在设计一个具有共享所有权语义的容器类型。它支持切片,因此切片共享所有权。我的问题之一是数据共享似乎会干扰 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 对象的非 const 拷贝,而后者可以修改前者的元素。
  • 复制构造和赋值实现截然不同的操作。这就是我如何让 c = aa.slice(1, 3) = b 做正确的事情(实际上是非常不同的事情)。

我不确定我是否遇到了麻烦。问题:

  • 这种设计是否合适,还是会在以后造成问题?如果有,是哪一个?
  • 如果存在严重缺陷,如何修复/避免?

感谢任何提示。

最佳答案

您需要分离类型才能以 const 正确的方式正常工作。出于与您发现的非常相似的原因,iteratorconst_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>;

这将是解决问题的第一步。您很可能必须引入更多的间接寻址,以便能够从非常量版本正确构造 ConstVersions(可能通过使用 std::enable_if 等启用/禁用某些模板化复制构造函数)。正如我所说,如果您正在构建某种符合标准库的代码片段,我只会走这条路。如果您只是为您的游戏或类似的东西构建一个小实用程序,请忽略 const 正确性,不要浪费您的时间。

关于c++ - 具有共享所有者语义的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42462970/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com