Forum Replies Created

Viewing 15 posts - 226 through 240 (of 349 total)
  • Author
    Posts
  • in reply to: enum class declaration #107801
    RainerRainer
    Keymaster
        Up
        0
        Down
        ::

        Can you provide me more info? Maybe, you have a minimal runnable example. For example, I’m confused that your class Equation deals with QString. I would expect some kind of number.

        You will probably implement a switch statement based on the enumerators. Here is an alternative, using a dispatch table.

        #include <cmath>
        #include <functional>
        #include <iostream>
        #include <map>
        
        int main(){
        
          std::cout << std::endl;
        
          // dispatch table
          std::map< const char , std::function<double(double,double)> > dispTable{
            {'+',[](double a, double b){ return a + b;} },
            {'-',[](double a, double b){ return a - b;} },
            {'*',[](double a, double b){ return a * b;} },
            {'/',[](double a, double b){ return a / b;} } };
        
          // do the math
          std::cout << "3.5+4.5= " << dispTable['+'](3.5,4.5) << std::endl;
          std::cout << "3.5-4.5= " << dispTable['-'](3.5,4.5) << std::endl;
          std::cout << "3.5*4.5= " << dispTable['*'](3.5,4.5) << std::endl;
          std::cout << "3.5/4.5= " << dispTable['/'](3.5,4.5) << std::endl;
        
          // add a new operation
          dispTable['^']=  [](double a, double b){ return std::pow(a,b);};
          std::cout << "3.5^4.5= " << dispTable['^'](3.5,4.5) << std::endl;
        
          std::cout << std::endl;
        
        };
        

        I wrote a post about this technique:  https://www.modernescpp.com/index.php/functional-in-c-dispatch-table.

        in reply to: About forum session short expiration #107558
        RainerRainer
        Keymaster
            Up
            0
            Down
            ::

            Thanks.

            I assume this is a reasonable default.

            in reply to: Memory used by STL containers #106811
            RainerRainer
            Keymaster
                Up
                0
                Down
                ::

                This sentence is misleading: “Even when other containers seem more suited, such as map for O(log N) lookup performance or a list for efficient insertion in the middle, a vector will usually still perform better for containers up to a few KB in size.”

                The quote makes only sense if you assume that the elements of a vector are not sorted. In this case, the lookup complexity is O(N). If the vector is sorted, the lookup has also the complexity O(log N) because you can use a bisection strategy.  Here is the interesting observation. Although, both lookup mechanism (map versus sorted vector) have the same complexity O(log N), a vector will outperform a map because of its cache-friendly layout.

                in reply to: Memory used by STL containers #106761
                RainerRainer
                Keymaster
                    Up
                    0
                    Down
                    ::

                    The sequence containers std::array and a std::vector must occupy a contiguous memory block.

                    For the associative containers such as std::map and std::unordered_map, there are no implementation requirements but performance requirements. Consequentially, measurements about their memory consumption cannot be generalized.

                    RainerRainer
                    Keymaster
                        Up
                        0
                        Down
                        ::

                        Really? I cannot find me. Please give me a hint.

                        in reply to: Memory used by STL containers #105194
                        RainerRainer
                        Keymaster
                            in reply to: std::swap for user defined types #105193
                            RainerRainer
                            Keymaster
                                Up
                                0
                                Down
                                ::
                                1. A value type is a type whose identity is based on its values and not on its identity. Typcial value types are money or date. I talk more about value types in my “Design Patterns and Architectural Patterns with C++” mentoring.
                                2. You should use the specializations of std::swap if available.
                                3. A user-defined swap member function is essential for the copy-and-swap idiom. The copy-and-swap idiom gives you transactional semantics for the copy assignment and move assignment operator. This will also be part of the “Design Patterns and Architectural Patterns with C++” mentoring. Here is a short code snippet.

                                  class Cont {
                                   public:
                                      // ...
                                      Cont& operator = (const Cont& rhs);
                                      Cont& operator = (Cont&& rhs) noexcept;
                                      friend void swap(Cont& lhs, Cont& rhs) noexcept {
                                          swap(lhs.size, rhs.size);
                                          swap(lhs.pdata, rhs.pdata);
                                  }
                                   private:
                                      int* pData;
                                      std::size_t size;
                                  };
                                  
                                  Cont& Cont::operator = (const Cont& rhs) {
                                      Cont tmp(rhs);              
                                      swap(*this, tmp);           
                                      return *this;
                                  }
                                  
                                  Cont& Cont::operator = (Cont&& rhs) {
                                      Cont tmp(std::move(rhs));  
                                      swap(*this, tmp);          
                                      return *this;
                                  }
                                  
                                in reply to: Observer Pattern over Library Boarders #104949
                                RainerRainer
                                Keymaster
                                    Up
                                    0
                                    Down
                                    ::

                                    Here are two ways using std::bind or lambda expressions:

                                    #include <functional>
                                    #include <iostream>
                                    
                                    class ObserverInterface
                                    {
                                    public:
                                    	virtual ~ObserverInterface() {}
                                    	virtual void update(int message) = 0;
                                    };
                                    
                                    class ObservableAdapter: public ObserverInterface
                                    {
                                    public:
                                    
                                    	ObservableAdapter(std::function<void(int)> call): callable(call) {}
                                    
                                    
                                    	void update(int message)
                                    	{
                                    		callable(message);
                                    	}
                                    
                                    private:
                                    	ObservableAdapter();
                                    	std::function<void(int)> callable;
                                    };
                                    
                                    
                                    void dummy(int) { 
                                        std::cout << "Do something as function\n";
                                    }
                                    
                                    struct Dummy{
                                        void operator()(int) const {
                                            std::cout << "Do something as function object\n";
                                        }
                                        void func(int) const {
                                            std::cout << "Do something as a member function\n";
                                        }
                                    };
                                    
                                    int main() {
                                    
                                        ObservableAdapter observer{[](int){ std::cout << "Do something as lambda\n"; }};
                                        observer.update(10);
                                    
                                        ObservableAdapter observer2{dummy};
                                        observer2.update(10);
                                    
                                        ObservableAdapter observer3{Dummy()};
                                        observer3.update(10);
                                      
                                        Dummy dummy;
                                        ObservableAdapter observer4{std::bind(&Dummy::func, &dummy, 5)};
                                        observer4.update(10);
                                    
                                        ObservableAdapter observer5{[dummy](int){ dummy.func(5); }};
                                        observer5.update(10);
                                    
                                    }
                                    
                                    1. std::bind creates a callable: std::bind(&Dummy::func, &dummy, 5). Because you invoke the function func on the object dummy, you have to provide it in the call.
                                    2. The lambda expressions binds the object dummy by copy and invokes the function func on it:  [dummy](int){ dummy.func(5); }

                                    Here is the example on Compiler Explorer: https://godbolt.org/z/z3GqWr1cz.

                                    in reply to: Question about const_cast #104651
                                    RainerRainer
                                    Keymaster
                                        Up
                                        0
                                        Down
                                        ::

                                        const_cast is a code smell but sometimes you have to deal with legacy software and you have to adapt the constness/volatileness of your variable.

                                        • You should prefer a const_cast to a C-cast (int i = (int) myValue;). A const_cast documents its intent, but not a C-cast.
                                        • Modifying a const declared object by removing its constness is undefined behavior: https://godbolt.org/z/6GWbbK71M.
                                        in reply to: Observer Pattern over Library Boarders #103914
                                        RainerRainer
                                        Keymaster
                                            Up
                                            0
                                            Down
                                            ::

                                            Your callback mechanism seems pretty complicated, and I don’t know why you need objects. I replaced it with a simple polymorphic function wrapper: std::function<void(int)>.

                                            #include <functional>
                                            #include <iostream>
                                            
                                            class ObserverInterface
                                            {
                                            public:
                                            	virtual ~ObserverInterface() {}
                                            	virtual void update(int message) = 0;
                                            };
                                            
                                            class ObservableAdapter: public ObserverInterface
                                            {
                                            public:
                                            
                                            	ObservableAdapter(std::function<void(int)> call): callable(call) {}
                                            
                                            
                                            	void update(int message)
                                            	{
                                            		callable(message);
                                            	}
                                            
                                            private:
                                            	ObservableAdapter();
                                            	std::function<void(int)> callable;
                                            };
                                            
                                            
                                            void dummy(int) { 
                                                std::cout << "Do something as function\n";
                                            }
                                            
                                            struct Dummy{
                                                void operator()(int) const {
                                                    std::cout << "Do something as function object\n";
                                                }
                                            };
                                            
                                            int main() {
                                            
                                                ObservableAdapter observer{[](int){ std::cout << "Do something as lambda\n"; }};
                                                observer.update(10);
                                            
                                                ObservableAdapter observer2{dummy};
                                                observer2.update(10);
                                            
                                                ObservableAdapter observer3{Dummy()};
                                                observer3.update(10);
                                            
                                            }
                                            

                                            Here is the running program in Compiler Explorer: https://godbolt.org/z/7E6jG7eae

                                            in reply to: Can we read the weak counter from control block? #103911
                                            RainerRainer
                                            Keymaster
                                                Up
                                                0
                                                Down
                                                ::

                                                No, there is no member function to get the use count of std::weak_ptr. Interestingly, boost’s weak_ptr implementation supports a use count for it.

                                                in reply to: microservices and c++ #103757
                                                RainerRainer
                                                Keymaster
                                                    Up
                                                    0
                                                    Down
                                                    ::

                                                    We used gSOAP. Our server was capable of handling 4000 clients concurrently. This was a typical client/server architecture. The server was a typical reactor based on select, poll, or epoll that accepts it client’s request and dispatched in to concurrent handlers. This is all what I know after 15 years.

                                                    Once more, the reason for gSOAP as SOAP implementation was performance. The Python server and the Java server based on SOAP was slower.

                                                    in reply to: microservices and c++ #103543
                                                    RainerRainer
                                                    Keymaster
                                                        Up
                                                        0
                                                        Down
                                                        ::

                                                        I had a similar discussion in my company in the past. We had a big client/server architecture in the automotive industry. Big means up to 4000 clients. Client and server sent permanently data. After a long evolution phase, we decided for SOAP  on the client and the server as communication infrastructure. This means that we use C++ on the server, and Java/Python on the client. The reason for SOAP was that it is a XML based protocol and had rich functionality. C++’s gsoap implementation was faster than the Java ones and pretty mature.

                                                        We decided against the following protocols: sun RPC, XML-RPC, CORBA, REST, homemade solution.

                                                        in reply to: Klaus Iglberger C++ Software Design #103541
                                                        RainerRainer
                                                        Keymaster
                                                            Up
                                                            0
                                                            Down
                                                            ::

                                                            I will read Klaus’s book in the next weeks. I know Klaus pretty well, and I expected such a book from him.

                                                             

                                                            in reply to: unique use of the keyword ‘using’ #102773
                                                            RainerRainer
                                                            Keymaster
                                                                Up
                                                                0
                                                                Down
                                                                ::

                                                                Make Volume a user-defind type. This improves readability and enforces type safety. Additionally, combine it with user-defined literals.

                                                                #include <iostream>
                                                                #include <ostream>
                                                                
                                                                namespace Units{
                                                                  class Volume{
                                                                    public:
                                                                      explicit Volume(double i):litre(i){}
                                                                
                                                                      friend Volume operator +(const Volume& a, const Volume& b){
                                                                        return Volume(a.litre + b.litre);
                                                                      }
                                                                      friend Volume operator -(const Volume& a, const Volume& b){
                                                                        return Volume(a.litre - b.litre);
                                                                      }
                                                                
                                                                      friend std::ostream& operator<< (std::ostream &out, const Volume& myDist){
                                                                        out << myDist.litre << " l";
                                                                         return out;
                                                                      }
                                                                    private:
                                                                      double litre;
                                                                
                                                                  };
                                                                
                                                                  namespace VolumeUnits {
                                                                    Volume operator "" _l(long double d){
                                                                      return Volume(d);
                                                                    }
                                                                    Volume operator "" _dl(long double m){
                                                                      return Volume(m/10);
                                                                    }
                                                                    Volume operator "" _cl(long double d){
                                                                      return Volume(d/100);
                                                                    }
                                                                    Volume operator "" _ml(long double c){
                                                                      return Volume(c/1000);
                                                                    }
                                                                  }
                                                                }
                                                                
                                                                using namespace Units::VolumeUnits;
                                                                
                                                                Units::Volume getVolume() {
                                                                    return 0.5_l + 3.5_ml - 10.5_dl;
                                                                }
                                                                
                                                                int main(){
                                                                
                                                                  std:: cout << '\n';
                                                                
                                                                  std::cout << "1.0_l: " << 1.0_l << '\n';
                                                                  std::cout << "1.0_dl: " << 1.0_dl << '\n';
                                                                  std::cout << "1.0_cl: " << 1.0_cl << '\n';
                                                                  std::cout << "1.0_ml: " << 1.0_ml << '\n';
                                                                
                                                                
                                                                  std::cout << '\n';
                                                                  std::cout << "1.0_l + 2.3_ml - 3.0_dl - 0.4_cl: " << 1.0_l + 2.3_ml - 3.0_dl - 0.4_cl << '\n';
                                                                  Units::Volume vol = getVolume();
                                                                  auto vol1 = getVolume();
                                                                  std::cout << "getVolume(): " << getVolume() << '\n';
                                                                  std::cout << '\n';
                                                                
                                                                }
                                                                

                                                                This is only a sketch.

                                                                Consider using the units library from Matesuz Pusz. It will be incorporated into an upcoming C++ standard. The necessary units are already defined: https://github.com/mpusz/units/blob/master/docs/framework/units.rst

                                                              Viewing 15 posts - 226 through 240 (of 349 total)