0

We are developping an embedded project, where we use C++14 and PIMPL for the OS-Abstraction. So we have Task-PIMPL-Interface which gets implemented in the referenced operating-system-SDK. Currently a small additional effort must be done because this class needs extra private attributes which unfortunately need to be accessed via a function directly.

This is needed because some of the Task-functions which are called from our initialization-management may be allocated at a different heap (overwrote malloc with our own heap-management), since we need to support different heaps at different places (and peripherals). And the task should keep info about the heap it was allocated in the first place. We will then store the initially used heap inside a task-attribute and check this when calling the other task-functions from outside to make sure any allocation that is done inside those functions is done at the correct heap.

Since I know all private variables should reside inside the Impl I am concerned that what I want to achieve would work. Since private member variables need to be initialized this would mean I need to recompile and modify the Impls as well. But C++11 brought default member initializer into the game.

so my guess was something like this:

struct Attributes
{
  uint16_t val1;
  uint16_t val2;
};

class PimplClass
{
  public:
    void callFuncA(); // in Impl

    /* access to the private attributes */
    Attributes& getAttr()
    { return attr_; } 
    void setAttr( Attributes& attr )
    { attr_ = attr; } 

  private:
    class PimplClassImpl;
    PimplClassImpl* pimpl_;
    /* the private attributes */
    Attributes attr_ = { 0, 0};
}

How does that behave to the interface and the implementation? Is the compile-firewall broken with that? We cannot directly tell if that makes a difference for us, since the Impl gets compiled anyway currently since our build-setup does not compile the Impls separately but we need to ensure the functionality for future build-setups, because then we may just link against a compiled lib.

Thanks!

NetoBF
  • 127
  • 6
  • Firstly, the Pimpl idiom does not the containing class to be the same type as what it delegates to (you have `PimplClass` containing a `PimpleClass *`). Second, your pimpl can provide an interface that is distinct from what its containing class provides (the implementation of member functions of the containing class will need visibility of the definition of the pimpl - the key is that your containing class does not expose its pimpl). – Peter Jun 05 '23 at 12:53
  • Note that your example has class "PimplClass" with nested class also "PimplClass" so it is tricky to discuss that code. If part of data is in envelope then the implementing code (like whatever is called by callFuncA) may need to get pointer to envelope. It is hard to see what difficulties you anticipate. – Öö Tiib Jun 05 '23 at 12:55
  • 1
    It seems you have a misunderstanding of what pimpl is and what "problems" it's meant to solve. I would advise you to take a look [here](https://en.cppreference.com/w/cpp/language/pimpl) or [there](https://learn.microsoft.com/en-us/cpp/cpp/pimpl-for-compile-time-encapsulation-modern-cpp?view=msvc-170) to fix that. – Fareanor Jun 05 '23 at 13:21
  • PIMPL interface classes typically have only a single pointer member variable. However, there is, in general, no reason why it couldn't have more member variables. If you then never change them, you still may maintain binary compatibility. – Daniel Langr Jun 05 '23 at 13:53
  • sorry, fixed the wrong implementation naming. – NetoBF Jun 05 '23 at 15:17
  • @Fareanor Except that I named the pimpl-type wrong I don't see what you mean. Can you please explain a bit more? I don't see any difference to the pimpl-interface-examples you linked to except they use unique_ptr. – NetoBF Jun 05 '23 at 15:23
  • @NetoBF It's not only the naming, the thing is that your private implementation should belong to your pimpl. And, the pimpl interface is not supposed to be exposed in the containing class. It seems you are using your pimpl more like an interface to extend your class, which is not what it's for (and will add a lot of clutter for nothing). I would really advise you to read the links I provided in my previous comment, it would help you better understand what problems pimpl solves and how to implement it properly. – Fareanor Jun 06 '23 at 07:59
  • If you need to expose the "private" implementation in the containing class, then pimpl is not what you are looking for. Maybe you need composition, or inheritance, etc... The thing with pimpl is that, while having amazing properties, it has a tendency to hurt the code readability. So using it just for the sake of using it without benefiting of its assets is not worth the effort :) – Fareanor Jun 06 '23 at 08:05
  • @Fareanor Thanks for the explanation. But I'm not sure that's the problem here, neither was it my question. Yes you can tell me it doesn't make sense, but that doesn't answer it. Yes, I can also use inheritance but that would be another question. The current implementations have all the stuff private as expected but that affords that some code gets copied all the way between different impls even if it would be the same for all. I wanted to reduce this effort. – NetoBF Jun 20 '23 at 08:46

0 Answers0