Reputation: 1397
Most Pimpl examples look as follows:
UPDATE: both cases fail, i.e. with and without namespaces. See answer from R Sahu at https://stackoverflow.com/a/57103016/2712726 . class Impl must be qualified with class name Simpl
// Simple.h
#include <memory>
class Simple {
struct Impl; // WORKS!
std::unique_ptr<Impl> impl_;
public:
Simple();
~Simple();
int get() const;
};
But this seems to fail in the real world where you would use namespaces. When namespaces are present, then the forward declaration has to be moved before the class declaration. Can anyone explain why?
// Simple.h but now with name spaces
namespace weired::example {
struct Impl; // OK! forwad declaration must go here
class Simple {
//struct Impl; // ERROR! incomplete type in ctor definition
std::unique_ptr<Impl> impl_;
public:
Simple();
~Simple();
int get() const;
};
}
I have tested this with gcc9
and clang8
with -std=c++11
up to c++2a
.
Just for completeness, here are the Simple.cpp and main.cpp files so you can run the example yourself:
// Simple.cpp
#include "Simple.h"
namespace weired::example {
struct Impl {int a,b;};
Simple::Simple() : impl_(new Impl{3,4}) {}
Simple::~Simple() = default;
int Simple::get() const
{
return impl_->a;
}
}
and
// main.cpp
#include "Simple.h"
#include <iostream>
int main () {
auto nonsense = weired::example::Simple{};
std::cout << nonsense.get() << '\n';
}
Upvotes: 2
Views: 438
Reputation: 206577
You may forward declare Impl
inside the class and outside the class, regardless of whether Simple
is defined in a namespace or globally.
The implementation of Impl
is almost identical in both cases.
namespace
Impl
is a peer class)The .h file
struct Impl;
class Simple { ... };
The .cpp file
// Define Impl
struct Impl { ... };
// Define Simple
Impl
is a nested class)The .h file
class Simple
{
struct Impl;
...
};
The .cpp file
// Define Impl
struct Simple::Impl { ... }; // Need the Simple:: scope here.
// Define Simple
namespace
Impl
is a peer class)The .h file
namespace weired::example {
struct Impl;
class Simple { ... };
}
The .cpp file
namespace weired::example {
// Define Impl
struct Impl { ... };
// Define Simple
}
Impl
is a nested class)The .h file
namespace weired::example {
class Simple
{
struct Impl;
...
};
}
The .cpp file
namespace weired::example {
// Define Impl
struct Simple::Impl { ... }; // Need the Simple:: scope here.
// Define Simple
}
Upvotes: 2