【问题标题】:A workaround for partial specialization of function template?功能模板部分专业化的解决方法?
【发布时间】:2012-09-02 15:18:51
【问题描述】:

考虑以下用于积分 pow 的元函数(这只是一个示例):

class Meta
{
    template<int N, typename T> static constexpr T ipow(T x)
    {
        return (N > 0) ? (x*ipow<N-1>(x)) 
                       : ((N < 0) ? (static_cast<T>(1)/ipow<N>(x)) 
                                  : (1))
    }
};

这样的函数的停止条件怎么写?

【问题讨论】:

  • @n.m.请发布解决方案您将如何重载该 ipow 函数模板,我已经完成了我的头:D
  • 有一个讨厌的黑客,我想你可以做return (N &gt; 0) ? (x * ipow&lt;(N - 1) * (N &gt; 0)&gt;(x)) : ((N &lt; 0) ? (static_cast&lt;T&gt;(1)/ipow&lt;-N * (N &lt; 0)&gt;(x)) : (1));。实在是太恶心了,不推荐。
  • @Mr.Anubis:JohannesSchaub-litb 打败了我,看看他的回答。
  • @JohannesSchaub-litb :为什么原始版本会导致无限递归而不是您讨厌的 hack(效果很好,我测试过,但我不明白为什么)?
  • @Vincent 因为我讨厌的 hack 使用 &lt;0&gt; 作为错误分支中的参数,而不是不断递减的数字。如果您在 0,则原始版本将实例化为 -1、-2、... 而不结束。即使分支的条件是编译时间常数(如您的情况),当前的(C++11)语言也不会阻止这种递归。

标签: c++ templates c++11 metaprogramming partial-specialization


【解决方案1】:

任何时候你问自己“如何模拟函数的偏特化”,你可以想“重载,让偏序决定哪个重载更特化”。

template<int N>
using int_ = std::integral_constant<int, N>;

class Meta
{
    template<int N, typename T> static constexpr T ipow(T x)
    {
        return ipow<N, T>(x, int_<(N < 0) ? -1 : N>());
    }

    template<int N, typename T> static constexpr T ipow(T x, int_<-1>)
    {
        //                             (-N) ??
        return static_cast<T>(1) / ipow<-N>(x, int_<-N>());
    }

    template<int N, typename T> static constexpr T ipow(T x, int_<N>)
    {
        return x * ipow<N-1>(x, int_<N-1>());
    }

    template<int N, typename T> static constexpr T ipow(T x, int_<0>)
    {
        return 1;
    }
};

我认为您想在注释标记位置传递 -N 而不是 N

【讨论】:

  • 为什么不直接删除ipow的显式模板参数?
  • @Xeo bah 然后它变得令人困惑,因为一些重载(-1 的重载)仍然需要“N”,所以它需要一个明确的参数。我想它是更有帮助的。
  • 啊,我明白了。是的,因为您基本上使用N 来进行方向和计数。
【解决方案2】:

一个简单的版本可能是这样的:

template <typename T, unsigned int N> struct pow_class
{
    static constexpr T power(T n) { return n * pow_class<T, N - 1>::power(n); }
};

template <typename T> struct pow_class<T, 0>
{
    static constexpr T power(T) { return 1; }
};

template <unsigned int N, typename T> constexpr T static_power(T n)
{
    return pow_class<T, N>::power(n);
}

用法:

auto p = static_power<5>(2);  // 32

【讨论】:

    【解决方案3】:

    只需在类模板中使用static 成员并专门化类模板。不过,为了方便起见,您可能希望创建一个转发函数模板。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-18
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多