I have the following CRTP classes which i want to use to implement a Visitor pattern
template <class Derived>
class Visitor
{
public:
Visitor() {
static_assert(!std::is_same<Visitor, Derived>::value,
"Visitor class cannot be instantiated directly. Use a derived class.");
}
virtual ~Visitor() = default;
virtual void visit(Derived&) = 0;
};
template <class Derived>
class Visitable
{
friend void Visitor<Derived>::visit(Derived&);
public:
Visitable() {
static_assert(!std::is_same<Visitable, Derived>::value,
"Visitable class cannot be instantiated directly. Use a derived class.");
}
template <class T>
void accept(T& visitor)
{
visitor.visit(static_cast<Derived &>(*this));
}
};
Then I define a visitable class
class Data : public Visitable<Data>
{
private:
std::string foo;
};
and a visitor for the class
class Printer : public Visitor<Data>
{
void visit(Data& data)
{
std::cout << data.foo << std::endl;
};
};
But the compiler tells me that "foo is a private member of 'Data'"... why does my friend specification not work as intended?
I also tried moving the "friend" to the derived class but it did not solve the issue.
class Data : public Visitable<Data>
{
friend void Visitor<Data>::visit(Data&); // instead of in Visitable
private:
std::string foo;
};
friend
ship is not inherited.
You have to add friend Printer;
in class Data
class Data : public Visitable<Data>
{
friend Printer;
private:
std::string foo;
};