what does one sacrifice with this pimpl alternative? - c++

I have, unfortunately, used Qt a lot (it purports to be many things that it is not) and since Qt uses the pimpl idiom extensively, I've gotten a lot of experience with the pimpl pattern as well and learned I don't like it. One alternative I like to use is:
// .hpp file
struct A
{
private:
struct B;
int a{};
};
// .cpp file
struct A::B
{
// replaces a private member function
static void f(A& a)
{
++a.a;
}
};
But what is sacrificed using this approach instead of using private function members or pimpl? Performance, binary compatibility? With pimpl, we know that it is performance, because of 1 level of added indirection.

Well, for one - this won't work if struct B needs to be a class template that takes arbitrary type parameters.

If A::B only contains static methods/data, there is no point in exposing that at all in the header. You can much simpler only implement those function in the .cpp file, without making them part of to the class.
// .hpp file
struct A
{
};
// .cpp file
void f(A& a)
{
// some function
// Might be called from the implementation of methods of `A`
}
So there is not really a reason to have a nested class in the first place.
On the other hand, if you do have non-static data/... in A::B that needs to be associated with instances of A (the situation where the pimpl idiom is used), then you somehow need to associate a A::B instance with every instance of A.
A straight forward way to do this would be to save a pointer to a A::B in each A. This is the pimpl idiom.

The idea of pimpl is to store data in each instance of A without making the internal structure of that data part of A's public interface.
Your code doesn't do that, so it doesn't replace pimpl.
In short, your code is a way to hide helper functions which are implementation details. pimpl does that and ALSO hides helper data which are implementation details.

Related

How to prevent impl details from being in the header file when a global function needs a pointer to the impl?

I'm using the pimpl idiom heavily in my code, mostly to reduce compilation time.
I have a situation where I'm calling into a C library. I have a C++ wrapper class which has its interface, and the gory details are all in the impl, of course:
class some_class {
public:
void some_init();
...
private:
class impl;
std::unique_ptr<impl> m_pimpl;
}
In the cpp file I have to register a callback with the C library where I get to give it a pointer. I want to forward this function call to the corresponding member function. The client (i.e. the user of this function) doesn't have to know about this detail at all:
static void from_c_func(void *ptr_to_class_impl) {
static_cast<some_class::impl *>(ptr_to_class_impl)->from_c_func();
}
void some_class::some_init() {
create_c_thing(static_cast<void *>(this->m_pimpl.get()), from_c_func);
}
The problem is that some_class::impl is declared private. I can only think of imperfect solutions:
Make the class impl; public in the header file. This is not ideal because it really should be private - it just happens to be an implementation detail that a non-class function needs to see it.
Put from_c_func in the header file and friend it. This is not ideal because the implementation details of some_class are leaking out. Changing the implementation may require changing the header file, which would then recompile a lot of things which don't need recompilation, which would make me unhappy.
Give from_c_func a pointer to some_class itself, and then call a function on some_class. This would require putting that function in the header file, which is again, an implementation detail - and it would have to be public anyway for the non-friend function to call it.
What to do? My best bet so far seems to be #1, but is there any better way?
You may move your function in impl
static void some_class::impl::from_c_func(void *ptr_to_class_impl) {
static_cast<some_class::impl *>(ptr_to_class_impl)->from_c_func();
}

Differences between these two PIMPL approaches

So when trying to get in touch with the PIMPL idiom one finds two common ways of doing it:
Using forward declaration outside a class:
class PimplClass;
class VisibleClass
{
private:
PimplClass* d_ptr;
};
Using forward declaration inside a class:
// *.hpp
class VisibleClass
{
private:
struct PimplClass;
PimplClass* d_ptr;
};
// *.cpp file:
struct VisibleClass::PimplClass
{
int x;
};
Two questions here:
To be honest I have no idea why the second one works. I mean the expression struct PimplClass I only do know from forward declaration but not within a class. Can someone please explain this to me?
Which solution to use? Where are the advantages or is it jsut a matter of taste?
It's a forward-declaration too, but PimplClass is scoped inside VisibleClass.
That second solution has the advantage of not dumping an internal type into the global namespace. Keeping PimplClass scoped inside VisibleClass makes complete sense.
In both cases, the Pimpl idiom should generally use a std::unique_ptr to tie the lifetimes of the interface and the Impl together, rather than a raw owning pointer.
You may do a forward declaration within class scope. So the second example is absolutely correct.
The main plus of second example is that your PimplClass can't be accessed from anywhere but from VisibleClass because it is declared (forward-declared) inside it's private section.

CRTP (Curiously Recurring Template Pattern) using a generic base template class instead of the derived class

I have been studying the CRTP lately and have come up of an idea to create a generic base template class using CRTP.
// Example.h
namespace A {
template <class TClass, typename T>
class Example {
public:
Example(T &someStruct) : m_someStruct_(someStruct)
{
}
~Example()
{
DoThis();
}
public:
void DoThis()
{
static_cast<TClass*>(this)->DoThat(m_someStruct_);
}
private:
T m_someStruct_;
};
}
// AsArgument.h
namespace A {
class AsArgument : public Example <AsArgument, SomeStruct> {
friend class Example <AsArgument, SomeStruct>;
private:
void DoThat(SomeStruct &someFun)
{
// Do something to someFun object.
// yehey(someFun);
printf("I want to do that! \n");
}
};
}
My goal is to use the base class object to access the derived class' functions and at the same time, separate the base and derived's implementation by including only the base class' header file and forward declare the derived class as a template argument.
I know the basics of what I can do with incomplete types but I can't seem to find information about templates.
Is it valid to forward declare the class TDerived argument instead of including the header file?
// SomeFile.cpp
#include "Example.h"
class A::AsArgument; // Forward declare this instead of including the AsArgument.h header file
namespace B {
void SomeClass::DoSomething()
{
SomeStruct fun;
Example <AsArgument, SomeStruct> example(fun);
}
}
I am not sure if this is a good design in creating a generic base template class, but my goal after establishing the base class is to easily create derived classes out of it and define the base class implementation on compile time.
It's actually some sort of a combination of RAII and CRTP.
I can actually achieve this by including the "AsArgument.h" file with "Example.h" but the separation between the base and the implementation is lost. And I keep getting compile error when I try to forward declare the AsArgument class (probably because of namespace issues I'm not fully aware of).
Any advise or is this kind of design even efficient and valid?
I'm not really sure what the design goal is here, but the rules about incomplete types apply in the same way whether or not you're talking about templates, you just need to think about where the template is instantiated.
In your case, you are trying to avoid including AsArgument.h in SomeFile.cpp. However, you instantiate the Example class template with the AsArgument class. That means that when you compile SomeFile.cpp, that translation unit does not know anything about the AsArgument class (because it doesn't see its declarations in the .h file), only that it exists.
However, as you might expect, you can't do much with a class if you only know it exists. You can't even hold it by value, since you don't know its size. You can't use any of its interface. In your example, there is no way the compiler can know that AsArgument::DoThat even exists (it doesn't necessarily need to know what it does, that can be left for the linker). Remember that Example is being instantiated in SomeFile.cpp, so that's where the compiler will need to know that DoThat exists.
So you need AsArgument.h. With a normal class, you could just put the declaration in the .h file, and put the definitions (the implementation) in the .cpp file. But AsArgument is a template class, so you can't do that in general. You can only do this for templates if you are templated on a limited number of classes, known in advance, and are willing to explicitly template on all of them.
I can't comment too much on the bigger picture, because I don't know what you are trying to do. I'm not very confident that CRTP is even a fit for you. CRTP is useful for certain things but it's not really the first tool that I turn to. Actually, now that I think of it: I quite rarely use it. In most cases if I'm going to use template based polymorphism, I could just hold the "child" directly and skip the base entirely, in many cases I don't feel like the base buys me enough.
I'd recommend including any compiler errors you have in future SO questions. Good luck!

c++ Forward Declaration design

From what i've read, i should use forward declarations whenever I can. I have classes like this ( where every fields are pointers because of forward declarations ) :
class A
{
// ...
A* a;
B* b;
C* c;
D* d;
E* e;
};
But there is problems with that.
1- This implies to call new and delete ( or at least new with smart pointers ) for every fields in constructor, while stack allocated fields don't need this.
2- I've read that stack allocation was faster than heap allocation.
3- Also that means that almost every fields on every classes should be pointers.
Am I doing the right way doing like my example class? Or am I missing something with forward declarations?
The example you've shown is an overkill. The suggestion to use forward declarations doesn't mean your code design is driven by forward declaration practices. Forward declarations are just implementation detail, the design prevails.
First decide whether you need aggregation or composition, then whether the forward declaration is appropriate.
Do prefer forward declaration over #include when the forward-declared type is part of your method signature, i.e. a parameter's type.
#include "OtherClass.h" // 'bad' practice
class OtherClass; // this is better than #include
....
class MyClass
{
void method(OtherClass *ptr);
}
It's not an absolute rule anyway as it's not always possible/convenient to use forward decls instead of includes.
The implication is inverse - you're not supposed to use pointers just in order to use forward declarations, but you're suppose to use forward declarations after you've taken a design decision (such as using pointers instead of objects as members) when you can.
So if it makes more sense to use objects, do so, and include the files you need. Don't use pointers just so you can forward-declare the classes.
If you are using pointers as members, prefer forward declaration than exposing complete class definition. Don't use pointers just to meet some rule blindly.
Technically spoken, you can (and should!) use a forward declaration, if the interface of your class doesn't depend on a fully qualified type. The compiler has to reserve enough space for members and add management functions at compile time - just using pointers or references in your class does not introduce dependencies on types.
BTW: Forward declaration isn't that new: In some C standard libraries, FILE is a typedef for a forward declared struct, which makes sense since FILE is always used for pointers in the whole public file API.
Use pointers or references for objects that the class doesn't own. But for objects that are owned by this class don't use forward declarations as a reason for choosing pointers.
If you really want to minimize compile time dependencies consider the PIMPL idom rather than turning all your members into pointers:
MyClass.h:
#include <memory>
class MyClassImpl;
class MyClass {
public:
MyClass();
~MyClass();
void doThing();
private:
std::unique_ptr<MyClassImpl> pimpl_;
};
MyClass.cpp
#include "MyClass.h"
#include "MyClassImpl.h"
MyClass::MyClass() { } // in .cpp so unique_ptr constructor has complete type
MyClass::~MyClass() { } // in .cpp so unique_ptr destructor has complete type
void MyClass::doThing(){
pimpl_->doThing();
}
MyClassImpl.h:
#include "A.h"
#include "B.h"
class MyClassImpl {
private:
A a_;
B b_;
public:
void doThing();
};
MyClassImpl.cpp:
#include "MyClassImpl.h"
void MyClassImpl::doThing() {
// Do stuff with a_, b_, etc...
}
This might not address performance concerns as you still have dynamic memory allocation but you would have to measure it to see.
In addition to the good answers already given: In cases where your class doesn't create an object but uses it privately (for instance some utility class), references can be used instead of pointers.
class UtilityClass; // forward declaration (even interfaces make sense here)
class MyClass {
public:
/// takes an UtilityClass for implementing some of its functions
MyClass(UtilityClass& u): util(u) {}
private:
UtilityClass& util;
// ...more details
};
These are cases, where forward declaration doesn't mean that objects have to be created on heap (as for your problems #1 and #2).

Static library: hiding private members from header file

I wish to compile part of my code as a static library to include in other project. Of course I'll have to distribute the compiled library and an header file containing the class declaration and the public members, but I don't know if it's possible to move all private members and declarations to a place different than the header file.
Example:
In the project.h file:
class MyClass
{
public:
MyClass();
void Give_me_an_input(int);
int Get_your_output();
private:
int a, b;
int MySecretAlgorithm();
};
In the .cpp file:
MyClass::MyClass()
{
a = 1;
b = 0;
}
void MyClass::Give_me_an_input(int c)
{
b = c;
}
int MyClass::Get_your_output()
{
return MySecretAlgorithm();
}
int MyClass::MySecretAlgorithm()
{
return (a + b);
}
Is there a way to move all private members int a, b; and int MySecretAlgorithm(); to a place different than the header file?
The pointer to implementation idiom can be used in such a scenario, commonly referred to as pimpl.
The basic idea is to take the implementation details out of the declaration
and simply have an opaque pointer to the implementation details.
std::unique_ptr is used in the the following example; but you could of course just use normal pointers.
// my_class declaration unit.
class my_class {
private:
class impl;
unique_ptr<impl> pimpl;
public:
};
// my_class implementation unit
class my_class::impl {
int whatever;
int whenever;
};
my_class::my_class(): pimpl( new impl )
{
}
Over the years I've seen some hacks to do this, but I don't think they are worth it. If your library is reasonably 'chunky' (ie: no method is being called a billion times a microsecond); and you can re-write chunks of your code...
You might consider making all the public stuff an abstract class (all virtual = 0) and then deriving your concrete classes from it.
Down sides of this:
- All your public calls become virtual (some optimizations can bypass this, but not often).
- You can't 'new up' your classes anymore, you'll need to implement a factory pattern.
The problem with any of the other hacks I'm familiar with is that they basically declare the methods in one set of headers, and then redeclare the same things with the 'real' implementation in private headers - depending on the linker to match up the names. A couple problems here are:
Maintaining this mess sucks. You can't use an #ifdef because it sounds like you want to physically hide your implementation. So you have dual maintaining, or a build step that generates your public headers.
Can only be used via pointer. You have to play games making constructors private and still have a factory because the compiler won't generate structs of the right size if you let the client gen it by value (or even with new).
Finally, I once saw a hack where the programmer tried to declare a byte array in the private area of the 'public' class so that the client code could still declare by value or 'new' it themselves. This suffers all the previous problems, plus you probably don't want to have to 'know' the size of the structs since they depend on packing and alignment. Your 'build step' would more or less have to have a runtime component that used sizeof() - and now you have a versioning problem if you want to change the size of the struct/class.