c++ power of integer, template meta programming

后端 未结 4 1056
抹茶落季
抹茶落季 2020-12-08 17:01

I want to make a function which returns a power of integer. Please read the fmuecke\'s solution in power of an integer in c++ .

However, I want to generalize his so

4条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-08 17:07

    When you find yourself in need of partially specializing a function template (beware, this does not mean that in this case you are in need, as DyP's answer shows), you may either resort to overloading (see the last update at the end of this answer) or, if that's not possible, wrap that function template into a class template, and have a static, non-template member function replace your original function template (and its specializations):

    namespace detail
    {
        template
        struct helper
        {
            static constexpr T pow(const T x){
                return helper::pow(x) * x;
            }
        };
    
        template
        struct helper // Unnecessary specialization! (see the edit)
        {
            static constexpr T pow(const T x){
                return x;
            }
        };
    
        template
        struct helper
        {
            static constexpr T pow(const T x){
                return 1;
            }
        };
    }
    

    Then, you could provide a helper function template that delegates to the specialization of your helper class template:

    template
    T constexpr pow(T const x)
    {
        return detail::helper::pow(x);
    }
    

    Here is a live example.

    EDIT:

    Notice, that the specialization for N == 1 is actually not necessary. I kept it in the original text because the purpose of this answer was mainly to show how to workaround the impossibility of partially specializing function templates in general - so I translated the original program piece-by-piece.

    As noted by Dyp in the comments, however, this would be enough:

    namespace detail
    {
        template
        struct helper
        {
            static constexpr T pow(const T x){
                return helper::pow(x) * x;
            }
        };
    
        template
        struct helper
        {
            static constexpr T pow(const T x){
                return 1;
            }
        };
    }
    

    UPDATE:

    As a further remark, please keep in mind that even when you can specialize function templates (e.g. with explicit - not partial - specializations), it is generally not a good idea to do so, because function template specialization does not normally behave as one would expect.

    Most of those situations that may seem to ask for function template specialization can actually be achieved through overloading, powered by well-known techniques such as tag dispatching. An example is proposed by Potatoswatter in the comments, pointing out that std::integral_constant could be used in this situation:

    template
    inline constexpr T pow(const T x, std::integral_constant){
        return 1;
    }
    
    template
    inline constexpr T pow(const T x, std::integral_constant){
        return pow(x, std::integral_constant()) * x;
    }
    
    template
    inline constexpr T pow(const T x)
    {
        return pow(x, std::integral_constant());
    }
    

    However, all these guidelines on "how to solve problems that seem to require function template partial specialization" should be taken into consideration when they are really needed. In this concrete case, as DyP showed in his answer, they are not.

提交回复
热议问题