在C++中是否可以在需要访问私有类成员的类外设置std::函数

wxclj1h5  于 2023-10-21  发布在  其他
关注(0)|答案(2)|浏览(104)

我正在写一个优先级队列,这是我的代码

#include <iostream>
#include<vector>
#include <functional>

template <class T>
class MaxPQ
{
public:
    MaxPQ(size_t size): container(size)
    {
    }

    MaxPQ(std::vector<T>& Raw)
    {
        //hard-code set it inside of class
        //this->setWrapper([=](size_t x, size_t y) -> bool { return this->container[x] < this->container[y]; });

        container.clear();
        for (const auto& val : Raw)
        {
            this->insert(val);
        }
    }

    MaxPQ(): container(0)
    {
    }

    ~MaxPQ()
    {
        container.clear();
    }

    void setWrapper(std::function<bool(size_t, size_t)> input)
    {
        compare_wrapper = input;
    }

    void insert(T newEle)
    {
        container.push_back(newEle);
        swim(container.size() - 1);
    }

    T delMax()
    {
        T result = max();
        swapByIndex(0, container.size() - 1);
        container.erase(container.end());
        sink(0);
        return result;
    }

    inline T max()
    {
        return container[0];
    }

    void swapByIndex(size_t Left, size_t Right)
    {
        using std::swap;
        swap(container[Left], container[Right]);
    }

    inline size_t left(size_t parent)
    {
        return parent * 2 + 1;
    }

    inline size_t right(size_t parent)
    {
        return parent * 2 + 2;
    }

    inline size_t parent(size_t child)
    {
        return (child - 1) >= 0 ? (child - 1) / 2 : -1;
    }

    void print()
    {
        using std::cout;
        for (const auto& val : container)
            cout << val << " ";
        cout << std::endl;
    }

private:
    std::vector<T> container;
    std::function<bool(size_t, size_t)> compare_wrapper;

    void swim(size_t targetIndex)
    {
        while (targetIndex > 0 && compare_wrapper(parent(targetIndex), targetIndex))
        {
            swapByIndex(parent(targetIndex), targetIndex);
            targetIndex = parent(targetIndex);
        }
    }

    void sink(size_t targetIndex)
    {
        while (left(targetIndex) < container.size())
        {
            size_t maxIndex = left(targetIndex);
            if (right(targetIndex) < container.size() && compare_wrapper(maxIndex, right(targetIndex)))
            {
                maxIndex = right(targetIndex);
            }
            if (compare_wrapper(maxIndex, targetIndex))
            {
                break;
            }
            swapByIndex(targetIndex, maxIndex);
            targetIndex = maxIndex;
        }
    }
};

int main()
{
    std::vector<int> temp{1, 8, 0, 9, 12, 4};
    auto myPQ = new MaxPQ<int>(temp);
    myPQ->setWrapper([=](size_t x, size_t y) -> bool
    {
//error here, trying to access private member `container`
        return myPQ->container[x] < myPQ->container[y];
    }); //set it out of class
    myPQ->print();
}

当我将compare硬编码为bool less(int,int)()时,所有代码都运行得很好bool less(int,int)()是一个私有的(因为没有必要让其他人调用它)成员函数,它将访问私有成员container,但其他人可能想要自定义函数,我猜它看起来像一个来自外部的函数,但可以像一个成员函数一样(可以访问私有成员)
那么我该怎么做呢(通过使用lambda函数或std::function来设置这样的 Package 器函数),我应该在哪里编写setWrapper函数,以及我应该在哪里调用它
这个设计好吗?
std::for_each如何设置它的函数 Package 器?
我是STL的新手,可能会有一些术语或概念上的错误,而且英语不是我的第一语言,请原谅我。
thanks in advance

k10s72fa

k10s72fa1#

如果将比较签名改为比较值,则不需要它。

template <class T>
class MaxPQ
{
public:

    using compare_func_type = std::function<bool(const T&, const T&)>; //use this instead of your old std::function<bool(size_t, size_t)>
...
}

如果你真的需要。您可以使用Friend declaration和函数来创建lambda。

template <class T>
class MaxPQ
{
public:

    template<typename V>
    friend std::function<bool(size_t, size_t)> create_compare(const MaxPQ<V>& myPQ);
...
}

template<typename V>
std::function<bool(size_t, size_t)> create_compare(const MaxPQ<V>& myPQ)
{
    return [=](size_t x, size_t y) -> bool //this line have problem because we capture by copy if there is some change in source element  after capture. it should cause undefined behavior.
    {
        return myPQ.container[x] < myPQ.container[y];
    };
}

int main()
{
   ...
   auto myPQ = new MaxPQ<int>(temp);
   myPQ->setWrapper(create_compare(*myPQ));
   ...
}
eh57zj3b

eh57zj3b2#

你想要访问的数据是私有的,所以在你的lambda中无法访问。
你可以实现这一点的方法之一是使它成为一个成员函数而不是lambda。当然,这会改变签名,除非您使用bind(或类似的东西)

相关问题