Reputation: 1708
First let me condense the relevant code, note the parameter movies
which produces the error:
// ActorGraph.hpp
class ActorGraph
{
protected:
class Movie; // definition further below
friend class MovieYearComparator;
int func(..., priority_queue<Movie, vector<Movie>, MovieYearComparator> &movies);
class Movie {...};
};
In the implementation file we have:
// 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)
{...}
However, g++ complains that MovieYearComparator
was not declared in this scope, referring to the func
declaration. I spelled everything correctly and this paradigm is working for other containers in the file, just not the priority queue. Note that Movie
is a very small class and I therefore chose to pass it by value.
Upvotes: 3
Views: 866
Reputation: 37616
When you forward-declare a class, you cannot do everything with it, you only have the right to use / store reference or pointer to it, e.g.:
struct A;
struct B {
A *_a; // Ok
B (A &a) : _a(&a) { } // Ok
};
void f (A a) { } // Oops!
The reason is simple: If you do not use a reference or a pointer, the compiler must know the size of the struct
/ class
when using it.
In your case, priority_queue
needs to use non-reference of the Comparer
, but since the first time you instantiate the template (in the definition of ActorGraph
) your Comparer
(MovieYearComparator
) is not a complete type, priority_queue
cannot be instantiated.
You need to define the MovieYearComparator
class before the first instantiation of your priority_queue
, e.g.:
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 {...};
};
If you want to keep your header "clean", you could only define the class in the header but implement the operator()
in the cpp file:
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 { }
Also note that since MovieYearComparator
is now an inner class of ActorGraph
, you do not need to make it a friend class.
Upvotes: 3