C 比较共享指针的堆栈

C++ Compare stacks of shared pointers

本文关键字:堆栈 指针 共享 比较      更新时间:2023-10-16

,假设我有一个堆栈,可以为int提供共享指针,就像以下:

#include <stack>
#include <memory>
using namespace std;
int main()
{
    stack<shared_ptr<int>> s1;
    stack<shared_ptr<int>> s2;
    shared_ptr<int> v1 = make_shared<int>(1);
    shared_ptr<int> v2 = make_shared<int>(1);
    s1.push(v1);
    s2.push(v2);
    bool areEqual = s1 == s2; // This is false
}

如何使堆栈比较shared_ptr指向的实际值,而不是指针本身?

std::stack具有受保护的成员c,它是基础容器类型的实例。您可以制作一个堆栈包装器,以访问该变量,然后比较基础容器的内容如下:

#include <iostream>
#include <stack>
#include <memory>
#include <algorithm>
using namespace std;
template<class stack_type>
struct stack_wrapper : stack_type
{
    auto begin() const
    {
        return stack_type::c.begin();
    }
    auto end() const
    {
        return stack_type::c.end();
    }
};
template<class stack_type>
const stack_wrapper<stack_type> &wrap(const stack_type &stack)
{
    return static_cast<const stack_wrapper<stack_type> &>(stack);
}
int main() {
    stack<shared_ptr<int>> s1;
    stack<shared_ptr<int>> s2;
    shared_ptr<int> v1 = make_shared<int>(1);
    shared_ptr<int> v2 = make_shared<int>(1);
    s1.push(v1);
    s2.push(v2);
    const auto &s1wrapper = wrap(s1);
    const auto &s2wrapper = wrap(s2);
    const auto is_equal = std::equal(s1wrapper.begin(),
        s1wrapper.end(),
        s2wrapper.begin(),
        s2wrapper.end(),
        [](auto &first, auto &second) {
            return first && second && *first == *second;
        });
    std::cout << is_equal << std::endl;
}

我喜欢 @realfresh的答案。它准确地说明了"封装"受保护的可访问性的真实程度。但是,将基类的子对象施放到派生类的子对象引用中,然后将其视为可以迅速导致不确定的行为。

提取c成员的想法是合理的。我们可以使用简单的实用程序而不会冒出UB的风险:

template<class S>
constexpr decltype(auto) stack_c(S&& s) {
    using base = std::decay_t<S>;
    struct extractor : base {
        using base::c;
    };
    constexpr auto c_ptr = &extractor::c;
    return std::forward<S>(s).*c_ptr;
} 

由于表达式&extractor::c的工作原理,我们实际上获得了指向basestd::stack专业化)成员的指针,名为cextractor的目的是通过使用声明使该名称可公开访问。

然后,我们将其转发给它,保留的值类别以及所有内容。这是@realfresh的使用std::equal的替换的下降:

bool areEqual = std::equal(
    stack_c(s1).begin(), stack_c(s1).end(),
    stack_c(s2).begin(), stack_c(s2).end(),
    [](auto const& p1, auto const& p2) {
        return first && second && (p1 == p2 || *p1 == *p2);
    }
); 

请参阅Live