Reputation: 1084
I have this error for the following code
incomplete type ‘Foo::Pimpl’ used in nested name specifier
AnotherFoo.hpp
struct AnotherFoo {
void methodAnotherFoo(Foo &);
};
AnotherFoo.cpp
#include "Foo.hpp"
#include "AnotherFoo.hpp"
void AnotherFoo::methodAnotherFoo(Foo &foo) {
// here i want to save the function pointer of methodPimpl(), std::function for ex:
std::function<void(void)> fn = std::bind(&Foo::Pimpl::methodPimpl, foo._pimpl); // <-- Here i am getting the error
}
Foo.hpp
struct Foo {
Foo();
class Pimpl;
std::shared_ptr<Pimpl> _pimpl;
};
Foo.cpp
#include "Foo.hpp"
struct Foo::Pimpl {
void methodPimpl(void) {}
};
Foo::Foo() : _pimpl(new Pimpl) {}
main.cpp
#include "Foo.hpp"
#include "AnotherFoo.hpp"
int main() {
Foo foo;
AnotherFoo anotherFoo;
anotherFoo.methodAnotherFoo(foo);
}
Does anyone have a good solution for how to fix this?
The main goal that I am trying to achieve is to keep the signature of the methodAnotherFoo
method hidden from the header files.
Upvotes: 4
Views: 769
Reputation: 1084
One solution that i found is to move the Pimpl implementation to AnotherFoo.cpp
Upvotes: -1
Reputation: 37513
Your Pimpl implementation is not correct. It should hide details while you are trying to access them directly from methodAnotherFoo
. So you should make implementation details private and provide a public proxy methods to manipulate stored implementation:
class Foo
{
public: Foo();
public: void method(void);
private: class Pimpl;
private: std::shared_ptr<Pimpl> _pimpl;
};
// Foo.cpp
struct Foo::Pimpl
{
void methodPimpl(void) {}
};
Foo::Foo() : _pimpl(new Pimpl) {}
void Foo::method(void) {_pimpl->method();}
And change the rest of the code to utilize those proxy methods instead of digging to implementation details:
void AnotherFoo::methodAnotherFoo(Foo &foo)
{
std::function<void(void)> fn = std::bind(&Foo::method, foo);
}
Upvotes: 0
Reputation: 15162
If AnotherFoo.cpp needs direct access to the implementation object it is going to have to see the definition of that type, there is no way around that. Perhaps add a "detail/foo.h" header that is meant for internal use like this.
Upvotes: 0
Reputation: 206577
The only file in which you may access details of Foo::Pimpl
is Foo.cpp, the file in which it is defined.
You may not access it in AnotherFoo.cpp.
Your choices are:
Change the implementation of AnotherFoo::methodAnotherFoo
to use only the public interface of Foo
.
Move the implementation of AnotherFoo::methodAnotherFoo
to Foo.cpp.
Upvotes: 4