未在范围内声明 - priority_queue C++的友元比较器类

Not declared in scope - friend comparator class for priority_queue C++

本文关键字:C++ 友元 比较器 queue 范围内 声明 priority      更新时间:2023-10-16

首先让我压缩相关代码,注意产生错误的参数movies

// ActorGraph.hpp
class ActorGraph
{
protected:
    class Movie; // definition further below
    friend class MovieYearComparator;
    int func(..., priority_queue<Movie, vector<Movie>, MovieYearComparator> &movies);
    class Movie {...};
};

在实现文件中,我们有:

// ActorGraph.cpp
class MovieYearComparator
{
public:
    bool operator() (const ActorGraph::Movie a, const ActorGraph::Movie b) const
    {
        // comparison operation
    }
};
ActorGraph::func(..., priority_queue<Movie, vector<Movie>, MovieYearComparator> &movies) 
{...}

但是,g++ 抱怨MovieYearComparator没有在此范围内声明,指的是func声明。我拼写正确,这种范式适用于文件中的其他容器,只是不适用于优先级队列。请注意,Movie是一个非常小的类,因此我选择按值传递它。

当你转发声明一个类时,你不能用它做所有事情,你只有使用/存储引用或指向它的指针的权利,例如:

struct A;
struct B {
    A *_a; // Ok
    B (A &a) : _a(&a) { } // Ok
};
void f (A a) { } // Oops!

原因很简单:如果不使用引用或指针,编译器在使用时必须知道struct/class的大小。

在您的情况下,priority_queue需要使用Comparer的非引用,但是由于您第一次实例化模板(在ActorGraph的定义中)您的ComparerMovieYearComparator)不是一个完整的类型,priority_queue无法实例化。

你需要在第一次实例化priority_queue之前定义MovieYearComparator类,例如:

class ActorGraph {
protected:
    class Movie; // definition further below
    class MovieYearComparator
    {
    public:
        // Use reference since your forward-declare Movie
        bool operator() (const ActorGraph::Movie const& a, 
                         const ActorGraph::Movie const& b) const {
            // comparison operation
        }
    };
    int func(..., priority_queue<Movie, vector<Movie>, MovieYearComparator> &movies);
    class Movie {...};
};

如果你想保持你的头"干净",你只能在头文件中定义类,但在 cpp 文件中实现operator()

class ActorGraph {
protected:
    class Movie; // definition further below
    struct MovieYearComparator {
        bool operator() (const ActorGraph::Movie const& a, 
                         const ActorGraph::Movie const& b) const;
    };
    int func(..., priority_queue<Movie, vector<Movie>, MovieYearComparator> &movies);
    class Movie {...};
};
// .cpp
bool ActorGraph::MovieYearComparator::operator() (const ActorGraph::Movie const& a, 
                                                  const ActorGraph::Movie const& b) const { }

另请注意,由于MovieYearComparator现在是ActorGraph的内部类,因此您不需要将其设置为友元类。