Uses of pointers non-type template parameters?

后端 未结 5 1032
小蘑菇
小蘑菇 2020-12-13 11:03

Has anyone ever used pointers/references/pointer-to-member (non-type) template parameters?
I\'m not aware of any (sane/real-world) scenario in which that C++ feature sho

5条回答
  •  渐次进展
    2020-12-13 11:15

    Pointer-to-function:

    Pointer-to-member-function and pointer-to-function non-type parameters are really useful for some delegates. It allows you to make really fast delegates.

    Ex:

    #include 
    struct CallIntDelegate
    {
        virtual void operator()(int i) const = 0;
    };
    
    template
    struct IntCaller : public CallIntDelegate
    {
        IntCaller(O* obj) : object(obj) {}
        void operator()(int i) const
        {
            // This line can easily optimized by the compiler
            // in object->func(i) (= normal function call, not pointer-to-member call)
            // Pointer-to-member calls are slower than regular function calls
            (object->*func)(i);
        }
    private:
        O* object;
    };
    
    void set(const CallIntDelegate& setValue)
    {
        setValue(42);
    }
    
    class test
    {
    public:
        void printAnswer(int i)
        {
            std::cout << "The answer is " << 2 * i << "\n";
        }
    };
    
    int main()
    {
        test obj;
        set(IntCaller(&obj));
    }
    

    Live example here.

    Pointer-to-data:

    You can use such non-type parameters to extend the visibility of a variable.

    For example, if you were coding a reflexion library (which might very useful for scripting), using a macro to let the user declare his classes for the library, you might want to store all data in a complex structure (which may change over time), and want some handle to use it.

    Example:

    #include 
    #include 
    
    struct complex_struct
    {
        void (*doSmth)();
    };
    
    struct complex_struct_handle
    {
        // functions
        virtual void doSmth() = 0;
    };
    
    template
    struct csh_imp : public complex_struct_handle
    {
        // implement function using S
        void doSmth()
        {
            // Optimization: simple pointer-to-member call,
            // instead of:
            // retrieve pointer-to-member, then call it.
            // And I think it can even be more optimized by the compiler.
            S->doSmth();
        }
    };
    
    class test
    {
        public:
            /* This function is generated by some macros
               The static variable is not made at class scope
               because the initialization of static class variables
               have to be done at namespace scope.
    
               IE:
                   class blah
                   {
                       SOME_MACRO(params)
                   };
               instead of:
                   class blah
                   {
                       SOME_MACRO1(params)
                   };
                   SOME_MACRO2(blah,other_params);
    
               The pointer-to-data template parameter allows the variable
               to be used outside of the function.
            */
            std::auto_ptr getHandle() const
            {
                static complex_struct myStruct = { &test::print };
                return std::auto_ptr(new csh_imp<&myStruct>());
            }
            static void print()
            {
                std::cout << "print 42!\n";
            }
    };
    
    int main()
    {
        test obj;
        obj.getHandle()->doSmth();
    }
    

    Sorry for the auto_ptr, shared_ptr is available neither on Codepad nor Ideone. Live example.

提交回复
热议问题