Forum Replies Created

Viewing 15 posts - 166 through 180 (of 349 total)
  • Author
    Posts
  • in reply to: Understand default member function #542612
    RainerRainer
    Keymaster
        Up
        0
        Down
        ::

        Move constructors typically “steal” the resources held by the argument, and leave the argument in some valid but otherwise indeterminate state.

        You can study the move constructor by studying the corresponding implementation:

         

        in reply to: User-defined literal, overload operator #542471
        RainerRainer
        Keymaster
            Up
            0
            Down
            ::

            Overloading the multiplication operator with a double from left and from right is the correct way to do it. You can automatically generate a few of the arithmetic operations with ugly CRTP tricks. For example, you can automatically generate a/b, b/a, a*b from b*a. Study the example crtpEquality.cpp.

            I discuss this sophisticated technique in my mentoring program “Design Patterns and Architectural Patterns with C++“.

            in reply to: const pointer containg const #542465
            RainerRainer
            Keymaster
                Up
                0
                Down
                ::

                The error message is misleading.

                int main() {
                    
                    int i = 13;
                    int j = 5;
                    int* p = &i; // p = &j and *p = i works
                    // int* const p = &i; =>  p = &j breaks
                    // const int* p = &i =>  *p = i breaks
                
                }
                

                When I make the pointer and the pointed-to element non-const, both assignment works. When I add constness to the pointer and the pointed-to element, one assignment will break.

                in reply to: compile vs run time #542462
                RainerRainer
                Keymaster
                    Up
                    0
                    Down
                    ::

                    I argue from the perspective of a constexpr function, but you can also apply it to a constexpr user-defined type. There are essential three cases for a constexpr declared function func.

                    constexpr int func(int a) {
                        return 2 * a;
                    }
                    
                    1. func is used in context that requires compile-time execution:
                      • inside static_assert
                      • for a c-array initialization
                      • inside a constexpr function
                      • you want to have the result of func on compile time: constexpr auto res = func(5)
                    2. func is invoked with a run-time argument => func(a) can only be executed at runtime
                    3. func can either run at compile time or runtime; it’s essentially a question of the optimizer
                    in reply to: Instantiating with {} or = #542299
                    RainerRainer
                    Keymaster
                        Up
                        0
                        Down
                        ::

                        Usually, a compiler transforms copy initialization into direct initialization. The C++ standard say: “When certain criteria are met, an implementation is allowed to omit the copy construction of a class object …” .When I use the following program in Compiler Explorer without and with maximum optimization, I see a small difference with maximum optimization for a std::string but not for an int.

                        #include <iostream>
                        #include <string>
                        
                        int main() {
                            
                            std::string s {"Hello"};       // (1)
                            std::string s2 = "Hello";      // (2)
                        
                            std::cout << s << " " << s2;
                        
                            int a1{5};
                            int a2 = 5;
                        
                            std::cout << a1 << " " << a2;
                        
                        }
                        

                        The copy initialization for the std::string s2 generates an additional assembler mov instruction (line 15). Compare the following screenshot of (1) and (2) in den example above:

                        Without optimization, I can neither observe a difference for a std::string or int.

                        Rule of thumb: prefer direct initialization

                        in reply to: Composition vs. inheritance #542291
                        RainerRainer
                        Keymaster
                            Up
                            0
                            Down
                            ::

                            Sure. Dependency injection is the typical way to replace the singleton pattern.

                            in reply to: Composition vs. inheritance #541746
                            RainerRainer
                            Keymaster
                                Up
                                1
                                Down
                                ::

                                Image, you want to sell cars. When your customer comes, you can decide, which car you want to assemble. You can even change a wheel of the car during runtime. You simply have to implement a member function changeWheel on the car.

                                virtual void changeWheel(std::unique_ptr<Wheel> wh) = 0;
                                

                                By the way, this is an application of the strategy pattern or dependency injection. Both techniques are based on composition.

                                in reply to: Return preserves const? #484363
                                RainerRainer
                                Keymaster
                                    Up
                                    0
                                    Down
                                    ::

                                    This following program shows the issue.

                                    #include <functional>
                                    #include <iostream>
                                    #include <string>
                                    
                                    std::function<std::string()> makeLambda() {
                                      const std::string val = "on stack created";
                                      return [&val]{return val;};
                                    }
                                    
                                    int main(){
                                    
                                      auto bad = makeLambda();
                                      std::cout << bad();
                                    
                                    }
                                    

                                    The local variable var goes out of scope. The program has undefined behavior. I will discuss this in more detail in week 9.

                                    RainerRainer
                                    Keymaster
                                        Up
                                        0
                                        Down
                                        ::

                                        To put it together, this is your structure:

                                        struct FileHandler{
                                            virutual std::string Read() const = 0;
                                            virtual Write(std::string s) = 0;
                                        };
                                        
                                        class DiskFile: public FileHandler {
                                           ...
                                        };
                                        
                                        class MemoryFile: public FileHandler {
                                           ...
                                        };
                                        
                                        void NeedFileHandler(FileHandler* fHandler) {
                                          // reads and writes
                                        }
                                        

                                        After painting this picture, I understand your question. But there is some point, I don’t understand. In general, the correct place to check if an object is correctly created is the constructor. Consequentially, doing this validation step in the function is too late.

                                        in reply to: Industries and projects #461772
                                        RainerRainer
                                        Keymaster
                                            Up
                                            0
                                            Down
                                            ::

                                            I want to answer as a C++ trainer.

                                            • In Germany, 60 % of my customers are car related. Most are car suppliers such as Continental, E-Solutions, or Bosch. In the last years, I have had around 15 classes for Bosch a year worldwide.
                                            • 30 % of my customers are in the embedded domain – most of them in the medical area.
                                            • The remaining 10 % of customers are mainly from the financial domain.

                                            When I give classes outside Germany, the relations change. The car manufacturer and suppliers are not so dominant.

                                            in reply to: Ping pong exercise – only one condition variable #457278
                                            RainerRainer
                                            Keymaster
                                                Up
                                                1
                                                Down
                                                ::

                                                Great. Your solution is correct and is easier to understand.

                                                in reply to: Threads and Mutexes #457277
                                                RainerRainer
                                                Keymaster
                                                    Up
                                                    0
                                                    Down
                                                    ::

                                                    Exactly. I will present the concurrency pattern in the “Design Patterns in Architectural Patterns with C++” mentoring program (weeks 14 – 16). In this mentoring program, I explain only the techniques. In particular, I will present Strategized Locking, Scoped Locking, and the Thread-Safe Interface, to only name a few.

                                                    in reply to: Ping pong exercise #457270
                                                    RainerRainer
                                                    Keymaster
                                                        Up
                                                        0
                                                        Down
                                                        ::

                                                        void setTrue(){
                                                        
                                                          while(counter <= COUNTLIMIT){
                                                        
                                                            std::unique_lock<std::mutex> lck(mutex_);
                                                            condVar1.wait(lck, []{return dataReady == false;});
                                                            dataReady= true;
                                                            ++counter;
                                                            std::cout << dataReady << '\n';
                                                            condVar2.notify_one();
                                                        
                                                          }
                                                        }
                                                        

                                                        You have to distinguish two cases:

                                                        The call condVar1.wait(lck, []{return dataReady == false;}); is

                                                        1. Not successful: unlocks the mutex and puts the thread in a blocked state
                                                        2. Successful: The mutex is still locked until the lck goes out of scope. The std::unique_lock lck is responsible for unlocking the mutex.

                                                        This means that the mutex cannot be acquired two times in a row.

                                                        in reply to: User-defined literal, overload operator #452864
                                                        RainerRainer
                                                        Keymaster
                                                            Up
                                                            0
                                                            Down
                                                            ::

                                                            friend MyDistance operator *(double n, const MyDistance& b){ 
                                                                return MyDistance(n*b.m);
                                                            }
                                                            

                                                            Also, this code is correct. You have a different issue. I assume this must be due to your build process. How do you compile and link your programs?

                                                            in reply to: std::lock vs. std::scoped_lock #425551
                                                            RainerRainer
                                                            Keymaster
                                                                Up
                                                                1
                                                                Down
                                                                ::

                                                                Here is the short answer: To make it short. When you use mutexex, use a std::scoped_lock.

                                                                And here is, why:

                                                                std::lock (C++11) and std::scoped_lock (C++17). Both lock their underlying objects, but here is the difference:

                                                                • std::lock locks only it’s underlying lock-like type. std::lock is no owner. Consequentially, you invoke std::lock with an owner such as std::unique_lock.
                                                                • std::scoped_lock is an owner modelling RAII. It locks in mutex-like type in its constructor and unlocks it in its destructor.

                                                                Referring to your example. std::lock only locks but not unlock its mutex. To see the difference, I add the unlock class manually: https://godbolt.org/z/K4M6vnfWd

                                                                 

                                                                 

                                                                 

                                                              Viewing 15 posts - 166 through 180 (of 349 total)