вторник, 12 марта 2019 г.

[prog.c++] C++Modules: there is no place for simplicity and beauty in C++?

C++Modules has been accepted in C++20. Nobody has a real experience with those modules and only few understand what C++Modules are. I don't understand that too. Moreover I don't read accepted Modules proposal yet. But I read a wonderful post "Understanding C++ Modules: Part 1: Hello Modules, and Module Units" and want to share some impressions.

It seems that simplicity and understandability weren't friends of C++ anytime in the past. But C++Modules lifts this up on another level.

It obvious that work on C++ standards is performed by very smart people. But sometimes you have to be as smart as they if not smarter to understand some of the new C++ additions and to find some beauty in them. C++Modules is an example.

Unfortunately I'm not as smart to participate in the evolution of C++ language. I'm just a (very ordinary) user of C++ and use C++ as a tool for solving my and my client's problems. Because of that, I can understand that there were some reasons to accept C++Modules in that form. But it's very hard to find and understand those reasons.

I can't understand why there are different types of module units (module interface, module implementation, module interface partition, module implementation partition, primary module interface) and very strange looking sentences like "export import :something;". Why not just:

module greeting;

export {

   public import another_module; // Instead of export import another_module.

   ... // Some ordinary C++ code.

// interface.

implementation {

   ... // Some ordinary C++ code.

// implementation.

If we have to deal with very big amount of code for a module we can simply use old #include directive:

module greeting;

export {

   public import another_module; // Instead of export import another_module.

   #include "some_declarations.hpp"
   #include "some_more_declations.hpp"

// interface.

implementation {

   #include "some_implementations.cpp"
   #include "some_more_implementations.cpp"
   #include "yet_more_implementations.cpp"

// implementation.

It's also hard to understand why modules and namespaces are orthogonal. Namespaces played their role in the pre-Modules world where we had only headers files and namespaces were used for "modularization" of C++ code.

But it's hard to imagine why we can write something like that:

import hello;

int main() {
   bye::tell();
}

From experience with different languages I expect that "import hello" introduces stuff from "hello" namespace. But in C++ we can "import hello" but receive "bye" namespace. Maybe there is some logic, but it seems also that "least surprise principle" doesn't live here.

I can suppose that there are some very important reasons why C++Modules and C++ namespaces are different entities. And I want to read the justification for this decision because as for me modules should make namespaces obsolete. With modules, we can get namespaces and nested namespaces (top-level modules and submodules).

Namespaces in C++ are open. It had two benefits in the past:

1. The content of namespace could be stored in several headers and source files. We opened namespace in one header file then reopened it in another file and so on.

But this benefit doesn't have sense with modules. IMHO.

2. An user can add specialization for its own types into external namespace.

But we can keep this benefit with modules if we add something like module's specialization (based on example from our json_dto library):

module json_dto specialization;

export {

   import my_module;

   template<>
   read_json_value( my_module::some_type & v, const rapidjson::Value & object )
   {
      ... // Specific version for some_type from my_module.
   }
}

Instead of conclusion.

I don't want to say that C++Modules proposal is bad. But it seems that C++Modules look much more complex than many of us expected. It also seems that C++Modules are intended to solve different problems than many of us can suppose.

It would be great to have some explanation about what C++Modules actually are, which problems they address, why C++Modules do it that way.

Without such explanation C++Modules remind me things like "export template" and "throw specification" from C++98 and "concept maps" from C++0x. They looked good in theory, but were deprecated or/and eliminated later.