Announcement

Collapse
No announcement yet.

Coroutines & Modules Added For C++20

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    Originally posted by atomsymbol View Post
    The use cases are (class T):
    1. Accessing a T's field directly
    2. Calling a function/method/constructor/destructor which uses the inline keyword and accesses a T's field
    3. Instantiating T on the stack - although after some though this still does not require the knowledge of T's fields, just the knowledge of T's size and alignment
    4. Static variables of type T - although after some though this still does not require the knowledge of T's fields, just the knowledge of T's size and alignment
    The only use cases are just 1 and 2. This slightly contradicts your statement that there are many uses of classes which still require the visibility.

    For template classes, the use cases are still just 1 and 2.
    Yeah, no. It's called name mangling.

    Comment


    • #22
      Originally posted by Ananace View Post

      From how I understand modules to work, it is left up to the compiler to pass the necessary information (AST etc) between modules where necessary, instead of being the job of the preprocessor - which just naively inlines the entire header and all its includes.
      Skipping the preprocessor here speeds up compiling immensely as you no longer need to parse headers more than once between correctly built modules, but you still get full visibility into the definition, just as an AST or other compiler-friendly datastructure.
      In fact you will still need to declare the class/methods you want to export in a specific part of our code (I think they call it the module preambule). The compiler won't compute it for you. So this is still better that the #include model because you won't have the header files textually included in our files, but it won't save you from having the declaration and the implementation defined in different places. (Note that this is a reason why I'm not really excited about modules).

      Comment


      • #23
        Originally posted by bountykiller View Post

        In fact you will still need to declare the class/methods you want to export in a specific part of our code (I think they call it the module preambule). The compiler won't compute it for you. So this is still better that the #include model because you won't have the header files textually included in our files, but it won't save you from having the declaration and the implementation defined in different places. (Note that this is a reason why I'm not really excited about modules).
        so you cant import a module? the compiler should be able to use the same information that a header contains (except for macros and certain templates but those shouldnt exist in C++ anyway)

        Comment


        • #24
          Originally posted by atomsymbol View Post
          True, although the PImpl pattern require the programmer to define an extra class which would be unnecessary in some cases if the language&compiler allowed usage of classes (method calls) without knowledge of field types. Abstract interfaces still require #include directives due to instantiation via operator new of interface implementations, which is unnecessary because the invoking the constructor+operator_new does not need the caller to know the representation of class's fields.
          Interface class + factory method avoids requiring the caller to have visibility into the implementation. It's not so different than PImpl, except you have a virtual function table calling the implementation class instead of another layer of functions.

          Code:
          class Interface
          {
          public:
                  // factory method for constructing an instance.
              static Interface *create();
          
              virtual ~Interface() {}
              virtual void f() = 0;
          };
          Buried in a cpp file, somewhere:
          Code:
          class Impl: public Interface
          {
          public:
              void f();
          
          private:
              // some types from a non-public library dependency can go here
          };
          
          Interface *Interface::create()
          {
              return new Impl();
          }

          Comment


          • #25
            Originally posted by atomsymbol View Post

            The use cases are (class T):
            1. Accessing a T's field directly
            2. Calling a function/method/constructor/destructor which uses the inline keyword and accesses a T's field
            3. Instantiating T on the stack - although after some though this still does not require the knowledge of T's fields, just the knowledge of T's size and alignment
            4. Static variables of type T - although after some though this still does not require the knowledge of T's fields, just the knowledge of T's size and alignment
            The only use cases are just 1 and 2. This slightly contradicts your statement that there are many uses of classes which still require the visibility.

            For template classes, the use cases are still just 1 and 2.
            It's odd that you think the size and alignment requirements can be known apart from the other details of a type. Maybe in some imaginary language, but we're talking about actual C++. And while one can compute these in template expressions, you need to start with full visibility of the type. So, all of cases 1-4.

            Also, how about:
            • Deriving from T
            • static_cast< DerivedFromT * >( T * )
            • Passing T by value
            • Invoking T's default constructor, destructor, assignment operator, or copy-constructor?
            • sizeof (T)
            • new T()

            Sure, a lot of these boil down knowing size and alignment, but then we're talking about use cases and not underlying requirements.

            Comment


            • #26
              Modules? Coroutines? Seems like Dr. Wirth is getting the last laugh, after all.

              Comment


              • #27
                For what I've understood C++ modules are just the next evolutionary step for precompiled headers. Many C++ headers are really slow to parse so now you will get some core stuff as modules. I wouldn't expect them to be generally used in projects at least in near future beyond that scope.

                Comment


                • #28
                  Originally posted by coder View Post
                  It's odd that you think the size and alignment requirements can be known apart from the other details of a type. Maybe in some imaginary language, but we're talking about actual C++. And while one can compute these in template expressions, you need to start with full visibility of the type. So, all of cases 1-4.
                  I still think the requirement of knowing sizeof(T) and alignof(T) for cases 3&4 depends on compiler implementation and is thus compiler-specific. An imaginary compiler could postpone global&static&stack allocations to link time aggregating multiple compilation units where sizeof(T) and alignof(T) are known to at least one compilation unit (one .o/.so file). This would make the linking stage slightly more time consuming though, but I think it would have no effect on program runtime performance.

                  Originally posted by coder View Post
                  Also, how about:
                  • Deriving from T
                  • static_cast< DerivedFromT * >( T * )
                  • Passing T by value
                  • Invoking T's default constructor, destructor, assignment operator, or copy-constructor?
                  • sizeof (T)
                  • new T()

                  Sure, a lot of these boil down knowing size and alignment, but then we're talking about use cases and not underlying requirements.
                  Deriving from T: Good point. Unless the derived-class-code is accessing T's fields then just sizeof(T) is needed if sizeof(T) != sizeof(T derived).

                  Passing T by value: This case can be reduced to allocation of sizeof(T) bytes followed by invocation of the copy-constructor.

                  Invoking T's default constructor, destructor, assignment operator, or copy-constructor: These are plain function calls, unless inlining. Default constructor/etc are automatically marked as inline by current compilers - a current-compiler-specific feature.

                  new T(): This is a call to function "T* new_T()" created by the compiler in the single .cc file that can see the field types and thus knows sizeof(T).

                  Comment


                  • #29
                    Originally posted by atomsymbol View Post
                    [I]C++ forces the programmer to define types of fields of a struct/class before the struct/class is defined. This is putting a very strict constraint on the ordering of struct data types in the source code. You cannot call a virtual method (defined elsewhere !!!) before the struct definition has seen the definition of the types of its fields, while obviously the knowledge of fields is immaterial to the virtual method call.
                    are you off your meds? you can't call virtual method before virtual method declaration has been seen by compiler because otherwise compiler doesn't know it exists, it's virtual, and what arguments does it take. now virtual method declaration is located in the definition of containing struct along with fields, but fields have nothing to do with the matter
                    it is an example of clueless commentator with outrageous claims

                    Comment


                    • #30
                      Originally posted by wswartzendruber View Post
                      It will be very interesting to see how C++20's utility compares to Rust.
                      well, it obviously compares even better than c++17

                      Comment

                      Working...
                      X