简体   繁体   中英

Will the upcoming addition of modules in c++ fix/alleviate the need for the pimpl idiom?

The pimpl idiom, as far as I can tell, hides a private implementation behind a forward declared symbol name so it can be declared and used in the private cpp module.

Example: https://cpppatterns.com/patterns/pimpl.html

As far as I can tell, because the class hosint the pimpl needs to know about its structure (size, aligment), the pimpl must be indirect through a pointer of some sort.

(or allocated as a block of sufficient size then moved/created into the location where it is reinterpreted by cast later.)

Does the upcoming modules specification solve this in any way?

P0142R0

5.2.3 Exported Class Properties

An occasionally vexing rule of standard C++ is that of controls access, not visibil- ity. Eg a private member of a class is visible to, but not accessible to non-member entities. In particular, any change to a private member of a class is likely to trigger e-processing of any translation unit that depends on that class's definition even if the change does not affect the validity of dependent units. It is tempting to solve that problem with a module system. However, having two distinct sets of rules (visibility and accessibility) for class members strikes us as undesirable and poten- tially fertile source of confusion. Furthermore, we want to support mass-migration of existing codes to modules without programmers having to worry about class member name lookup rules: if you understand those rules today, then you do not have to learn new rules when you move to modules and you do not have to worry about how the classes you consume are provided (via modules or non-modules).

Rule 3 In general, any property of a class (eg completeness) that is computed in the export declaration part of a module is made available to importing modules as is.

As all properties of a class are visible to the importer, any change to those properties would be visible in the importer. I don't see modules solving the problem that PIMPL solves.

Private Module Fragments improve pimpl ergonomics according to this msvc blog post .

module;
#include <memory>
export module m;
struct Impl;

export
class S {
public:
  S();
  ~S();
  void do_stuff();
  Impl* get() const { return impl.get(); }
private:
  std::unique_ptr<Impl> impl;
};

module :private; // Everything beyond this point is not available to importers of 'm'.

struct Impl {
  void do_stuff() { }
};

S::S():
  impl{ std::make_unique<Impl>() }
{
}

S::~S() { }

void S::do_stuff() {
  impl->do_stuff();
}
import m;

int main() {
    S s;
    s.do_stuff();         // OK.
    s.get();              // OK: pointer to incomplete type.
    auto impl = *s.get(); // ill-formed: use of undefined type 'Impl'.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM