gpt4 book ai didi

C++ 模板 - 广义操作和实例之间成员的可见性

转载 作者:行者123 更新时间:2023-11-27 22:44:40 26 4
gpt4 key购买 nike

作为一些实践,我决定实现一个非完整的线程安全和通用堆栈。您可以在下面看到类模板的初始声明:

template <typename T>
class ThreadsafeStack {
public:
ThreadsafeStack() = default;

ThreadsafeStack(ThreadsafeStack<T> const&);
template <typename U>
ThreadsafeStack(ThreadsafeStack<U> const&);

~ThreadsafeStack() = default;

ThreadsafeStack<T>& operator=(ThreadsafeStack<T> const&);
template <typename U>
ThreadsafeStack<T>& operator=(ThreadsafeStack<U> const&);

void push(T new_value);
std::shared_ptr<T> pop();
void pop(T& value);
bool empty() const;
private:
std::stack<T> data;
mutable std::mutex m;
};

我的问题是关于通用复制操作(为简单起见,我暂时省略了移动操作)。例如,请参阅“正常”和广义赋值运算符的定义:

// "Normal"
template <typename T>
ThreadsafeStack<T>& ThreadsafeStack<T>::operator=(ThreadsafeStack<T> const& o)
{
if ((void*) this == (void*) &o) {
return *this;
}

std::lock(m, o.m);
std::lock_guard<std::mutex> lock1(m, std::adopt_lock);
std::lock_guard<std::mutex> lock2(o.m, std::adopt_lock);

data = o.data;

return *this;
}

// "Generalized"
template <typename T>
template <typename U>
ThreadsafeStack<T>& ThreadsafeStack<T>::operator=(ThreadsafeStack<U> const& o)
{
if ((void*) this == (void*) &o) {
return *this;
}

// ... ?

return *this;
}

使用这段代码,问题是成员 std::mutex mThreadsafeStack<U>不是从 ThreadsafeStack<T> 可见- 这样我就可以锁定 m但不是 o.m (与“正常”情况不同)。

(请注意,我必须锁定要复制的数据结构的互斥锁,期间不间断整个复制过程。我认为按元素锁定和释放都不会有效或逻辑上正确。假设我有一个由值 5、6、7 组成的堆栈;首先,我复制 5 但在那之后另一个线程弹出 6,所以我复制的下一个元素是 7...)

那么,你会如何解决上面的问题呢?

我已经考虑过以下解决方案:

  • 公开互斥锁成员(最坏的主意,不想那样做)。 (在我看来,使用成员函数返回对它们的引用是一个类似的糟糕的 OO 设计思想。)
  • 第二个:创建一个返回完整基础数据拷贝的公共(public)成员函数(请注意,这种方式锁定只能执行一次)。我认为更长但类似的解决方法可能是使用已经存在的界面。
  • 没有提供任何语言,更自然的方式来做到这一点? (例如,一些特殊语法表示特定模板的所有实例化出于此类目的查看彼此的私有(private)和 protected 成员。)

还尝试对主题进行一些研究:

  • C++ Templates - The Complete Guide 作者还指出在第 5 章中,由于这个问题,他们不得不使用 public制作拷贝的界面。尽管我觉得这是一本很棒的书,不幸的是它有点旧所以可能更有效率现在的解决方案。

  • 对于斯科特来说,这可能也是正确的(与某些项目有关)Meyer 的Effective C++:第 45 项提到“正常”和通用化复制构造函数/赋值运算符,但它还不够深入这个具体方向。

  • 在 SO 上阅读类似的问题,但在与广义操作的联系。

(注意:线程安全堆栈示例的基础知识来自 Anthony Williams 的 C++ Concurrency in Action。)

非常感谢您提前提供的任何帮助。

问候, Solr 特

最佳答案

制作ThreadSafeStack<U> ThreadSafeStack<T>的 friend :

template <typename T>
class ThreadsafeStack {
public:
template <typename U>
friend class ThreadSafeStack;
//...
};

template <typename T>
template <typename U>
ThreadsafeStack<T>& ThreadsafeStack<T>::operator=(ThreadsafeStack<U> const& o)
{
if ((void*) this == (void*) &o) {
return *this;
}

std::lock(m, o.m);
std::lock_guard<std::mutex> lock1(m, std::adopt_lock);
std::lock_guard<std::mutex> lock2(o.m, std::adopt_lock);

//...

return *this;
}

现在ThreadSafeStack<T>可以访问 ThreadSafeStack<U> 的私有(private)成员.您如何实际复制 std::stack<T>std::stack<U>仍然悬而未决;没有复制构造函数或赋值运算符可以做到这一点。

关于C++ 模板 - 广义操作和实例之间成员的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44687901/

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