Forum Replies Created

Viewing 15 posts - 241 through 255 (of 349 total)
  • Author
    Posts
  • in reply to: Constraining the template in stlAlgorithms.cpp #102135
    RainerRainer
    Keymaster
        Up
        1
        Down
        ::

        Here are three variations. All three use the fact that you can get the underlying type of a container Cont with Cont::value_type.

        1. Derive the type from the container:

          template <typename Cont>
          void doTheSame(Cont cont, typename Cont::value_type t){
          
        2. Use static_assert in the algorithm:

          template <typename Cont, typename T>
          void doTheSame(Cont cont, T t){
              static_assert(std::is_same<typename Cont::value_type, T>::value, "Must be same type");
          
        3. Use the concept std::same_as in C++20

          template <typename Cont, typename T>
              requires std::same_as<typename Cont::value_type,T>
          void doTheSame(Cont cont, T t)
          

        The solutions 2 and 3 do not allow implicit conversion. The types must exactly match. You can study my variations on the Compiler Explorer: https://godbolt.org/z/TW8G7Yvcz.

        in reply to: Pointers and Linked Objects #97212
        RainerRainer
        Keymaster
            Up
            0
            Down
            ::

            The five creational patterns in the book “Design Patterns: Elements of Reusable Object-Oriented Software” use as the running example a maze. I found C++ implementations of the pattern on BartVandewoestyne / Design-Patterns-GoF.

            I know the author Bart, because he was one of the proofreaders of my by “The C++ Standard Library“.

            in reply to: Performance experiment #96975
            RainerRainer
            Keymaster
                Up
                0
                Down
                ::

                I check the numbers. If there is a big performance gap between with and without optimization, I will analyze the generated the code in the Compiler Explorer. If I recognize that the optimizer is too aggressive, I will most of the time add a volatile variable.

                in reply to: Core Guideline R36 – whats with the ‘???’ #96599
                RainerRainer
                Keymaster
                    Up
                    0
                    Down
                    ::

                    Here are the three examples of rule R.36:

                    void share(shared_ptr<widget>);            // share -- "will" retain refcount (1)
                    
                    void reseat(shared_ptr<widget>&);          // "might" reseat ptr              (2)
                    
                    void may_share(const shared_ptr<widget>&); // "might" retain refcount         (3)
                    
                    1. The function share is an additional owner of the widget.
                    2. The function reseat may change the widget, shared by all owners of it.
                    3. The function may_share is not an owner of the widget. It is only borrowed. This is the general semantics of a function taking it argument by pointer or by reference. I see no added value here. A raw pointer to the widget or a reference would also be fine.
                    in reply to: Pointers and Linked Objects #95405
                    RainerRainer
                    Keymaster
                        Up
                        0
                        Down
                        ::

                        So far, I’m in the process of analyzing your program. I, therefore, simplified it a bit. Here are my first thoughts.

                        Your program has undefined behavior. The function get_cell returns a reference to a local: https://godbolt.org/z/58hWbYsM5 => Your Grid should be a std::vector<std::vector<Cell*>> for your strategy.

                        Now, get_cell returns a value: https://godbolt.org/z/jxEGqza8K. This is fine.

                         

                        in reply to: Programming at Compile Time by Rainer Grimm #92899
                        RainerRainer
                        Keymaster
                            Up
                            0
                            Down
                            ::

                            Thanks a lot. I fixed both links.

                            in reply to: Re-assign a new type to alias #91988
                            RainerRainer
                            Keymaster
                                Up
                                0
                                Down
                                ::

                                Your type alias is another name for a type. Types are determined at compile time.  You can only define, but not change it.

                                Reassigning a type alias would be a run time thing. The compiler would, therefore, lose all type information.

                                 

                                 

                                in reply to: Meta-functions to check against constexpr #91985
                                RainerRainer
                                Keymaster
                                    Up
                                    0
                                    Down
                                    ::

                                    I don’t know why. I can only quote cppreference.com: “If T is a const-qualified type (that is, const, or const volatile), provides the member constant value equal to true. For any other type, value is false.”

                                     

                                    in reply to: Meta-functions is_member… of type-traits library #91983
                                    RainerRainer
                                    Keymaster
                                        Up
                                        0
                                        Down
                                        ::

                                        You declared point of the correct type. This must return true.

                                        Typically, you do it the other way around. You have a member pointer, and you want to ask what kind of pointer this is: member object pointer or member function pointer.

                                        I modified your example and asked for the pointer types of A::a, and A::f.

                                        #include <iostream>
                                        #include <type_traits>
                                        
                                        struct A {
                                            int a;
                                            int f(int) { return 2011; }
                                        };
                                        
                                        int main()
                                        {
                                            std::cout << std::boolalpha << '\n';
                                        
                                            A a;
                                        
                                            std::cout << "std::is_member_pointer<decltype(&A::a)>::value: " << std::is_member_pointer<decltype(&A::a)>::value << '\n';
                                            std::cout << "std::is_member_pointer<decltype(&A::f)>::value: " << std::is_member_pointer<decltype(&A::f)>::value << '\n';
                                        
                                            std::cout << '\n';
                                           
                                        
                                            std::cout << "std::is_member_object_pointer<decltype(&A::a)>::value: " << std::is_member_object_pointer<decltype(&A::a)>::value << '\n';
                                            std::cout << "std::is_member_object_pointer<decltype(&A::f)>::value: " << std::is_member_object_pointer<decltype(&A::f)>::value << '\n';
                                        
                                            std::cout << '\n';
                                        
                                            std::cout << "std::is_member_function_pointer<decltype(&A::a)>::value: " << std::is_member_function_pointer<decltype(&A::a)>::value << '\n';
                                            std::cout << "std::is_member_function_pointer<decltype(&A::f)>::value: " << std::is_member_function_pointer<decltype(&A::f)>::value << '\n';
                                        
                                            std::cout << '\n';
                                        
                                            std::cout << "std::is_same<int A::*, decltype(&A::a)>::value: " << std::is_same<int A::*, decltype(&A::a)>::value << '\n';
                                            std::cout << "std::is_same<double A::*, decltype(&A::a)>::value: " << std::is_same<double A::*, decltype(&A::a)>::value << '\n';
                                        
                                            std::cout << '\n';
                                        
                                            std::cout << "std::is_same<int (A::*)(int), decltype(&A::f)>::value: " << std::is_same<int (A::*)(int), decltype(&A::f)>::value << '\n';
                                            std::cout << "std::is_same<int (A::*)(double), decltype(&A::f)>::value: " << std::is_same<int (A::*)(double), decltype(&A::f)>::value << '\n';
                                        
                                        
                                        }
                                        

                                        Here is the corresponding compiler explorer example: https://godbolt.org/z/vj8MWvP4M.

                                        in reply to: Print values at compile-time #88626
                                        RainerRainer
                                        Keymaster
                                            Up
                                            0
                                            Down
                                            ::

                                            There is no way to get output at compile time.

                                            You can either

                                            • enforce a compile time error with static_assert (C++11) or Concepts (C++20)
                                            • visualize the template instantiation process with C++ Insights or the Metashell
                                            in reply to: Variadic function templates for same type #88625
                                            RainerRainer
                                            Keymaster
                                                Up
                                                0
                                                Down
                                                ::

                                                Here are my thoughts:

                                                  • Use non-type template parameters:

                                                    template <int T, int... Ts >
                                                    constexpr int testIntSum()
                                                    {
                                                        int initialValueIncreased{ T };
                                                    
                                                        auto doSumOperation = [&](const auto& singleOtherValue)
                                                        {
                                                            //filter out the non-arithmetic types
                                                            if constexpr( std::is_arithmetic_v< std::remove_reference_t< decltype( singleOtherValue ) > >)
                                                            {
                                                                initialValueIncreased += singleOtherValue;
                                                            }
                                                        };
                                                    
                                                        (..., doSumOperation(Ts));
                                                    
                                                        return initialValueIncreased;
                                                    
                                                  • Use Fold Expressions in C++17: https://www.modernescpp.com/index.php/from-variadic-templates-to-fold-expressions
                                                  • Use a std::initializer_list:
                                                    #include <iostream>
                                                    #include <numeric>
                                                    #include <initializer_list>
                                                    
                                                    template <typename T>
                                                    T sum(std::initializer_list<T>  args) {
                                                       return std::accumulate(args.begin(), args.end(), T{});
                                                    }
                                                    
                                                    int main() {
                                                        std::cout << sum({1, 2, 3, 4, 5});
                                                    }
                                                    
                                                  • Use a concept in C++20:
                                                    constexpr std::integral auto testGenericSum(const std::integral auto& initialValue, const std::integral auto&... otherValues)
                                                    {
                                                        std::integral auto initialValueIncreased{ initialValue };
                                                    
                                                        auto doSumOperation = [&](const auto& singleOtherValue)
                                                        {
                                                            //filter out the non-arithmetic types
                                                            if constexpr( std::is_arithmetic_v< std::remove_reference_t< decltype( singleOtherValue ) > >)
                                                            {
                                                                initialValueIncreased += singleOtherValue;
                                                            }
                                                        };
                                                    
                                                        (..., doSumOperation(otherValues));
                                                    
                                                        return initialValueIncreased;
                                                    }
                                                    

                                                    Only for completeness, but I don’t suggest this. You can also define a concept for a concrete type. Additionally, I decayed in my example on the int:

                                                    #include <type_traits>
                                                    
                                                    template <typename T>
                                                    concept int_ = std::is_same_v<std::decay_t<T>, int>;
                                                    
                                                    int main() {
                                                    
                                                        static_assert(int_<int>, "no int");
                                                        static_assert(int_<int&>, "no int");
                                                        static_assert(int_<const int>, "no int");
                                                    
                                                    }
                                                    
                                                in reply to: inline in template variable definition #88616
                                                RainerRainer
                                                Keymaster
                                                    Up
                                                    1
                                                    Down
                                                    ::

                                                    You have to ensure, that a header or an entity is only included once in a translation unit. ⇒ You use include guards:

                                                    #ifndef INCLUDE_GUARD_H
                                                    #define INCLUDE_GUARD_H
                                                    
                                                    #include <myHeader.h>
                                                    
                                                    template < class T >
                                                    constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
                                                    
                                                    #endif /* INCLUDE_GUARD_HH */
                                                    

                                                    You have only the guarantee that the variable is_arithmetic_v is used once in one translation unit. Your program may have more than one translation unit. Consequentially, you have more than one usage of the variable is_arithmetic_v.

                                                    Here is the issue. Due to the internal linkage of the variable is_arithmetic_v, the variable is_arithmetic_v has more than one definition. This violates the One Definition Rule (ODR) and is undefined behavior.

                                                    An inline variable essentially means:

                                                    1. This entity might be defined in multiple translation units.
                                                    2. All those definitions are identical.
                                                    3. Merge them into one definition at link time.
                                                    in reply to: Video on week 17 template specialization – introspection #87861
                                                    RainerRainer
                                                    Keymaster
                                                        Up
                                                        0
                                                        Down
                                                        ::

                                                        You are right. This is intentional. I record this “Welcome and Overview” video a few days before the week starts.

                                                        RainerRainer
                                                        Keymaster
                                                            Up
                                                            0
                                                            Down
                                                            ::

                                                            Thanks a lot. I fixed it.

                                                            in reply to: inline in template variable definition #87270
                                                            RainerRainer
                                                            Keymaster
                                                                Up
                                                                0
                                                                Down
                                                                ::

                                                                inline is essentially about the one definition rule (ODR).

                                                                Thanks to inline, the variable is_arithmetic_v has external linkage. Without the keyword inline, using is_arithmetic_v is undefined behavior. You can read more about ODR in my following post: inline.

                                                              Viewing 15 posts - 241 through 255 (of 349 total)