如何在不复制和粘贴整个类体的情况下专门化模板?

时间:2013-04-14 18:42:51

标签: c++ templates template-specialization

我为移动平均线写了一个简单的类,它可以和AVR一起使用。

template<typename T, typename Tsum = int32_t>
class MovingAverage { ... }

但是现在我想把这个类专门用于float而不复制和粘贴整个类体并将所有T和Tsum更改为float并且我不需要使用两个模板参数。 Tsum是'sum'变量的类型,其中所有传递的T类型值都被总结。如果T是'uint8_t',最好使用'uint32_t'作为总和,但对于float或double,不需要使用具有更高精度的数据类型,因此我只需要一个参数用于此目的。我认为它可以这样工作:

typedef MovingAverage<float, float> MovingAverage<float>

或者这样:

template<>
class MovingAverage<float> : public MovingAverage<float, float> {};

但我错了,我找到了只需要编写代码两次的解决方案。

有没有办法只写一次这个类,然后按照我喜欢的方式专门化它? 提前谢谢!

2 个答案:

答案 0 :(得分:8)

如果你想要Tsum的不同默认类型,这应该外包给另一个可以指定的类,例如:

template< typename, typename = void >
struct DefaultSum { using type = int32_t; };

template< typename T >
struct DefaultSum< T, typename std::enable_if<
  std::is_floating_point< T >::value
>::type >
{ using type = T; };

template<typename T, typename Tsum = typename DefaultSum<T>::type >
class MovingAverage { ... }

答案 1 :(得分:5)

你可以写一个简单的 traits class

// general version
template<typename T>
struct sum_type
{
    typedef int32_t type;
};

// specialized version
template<>
struct sum_type<float>
{
    typedef float type;
};

// repeat for double, the solution from @DanielFrey is even more sophisticated 
// as it specializes all floating point types in one sweep.

然后在类模板中提取此类型

template<typename T, typename Tsum = typename sum_type<T>::type>
//                                   ^^^^^^^^ <-- dependent type disambiguation
class MovingAverage { ... };

请注意,这仅适用于MovingAverage具有定期参数化实现的情况。如果你实际上正在为float做一些特殊的事情(例如,重写表达式来处理浮点运算的非关联特性),那么你需要做更多的工作。

如果您认真使用C ++模板,请运行-not walk-到最近的书店并获取书籍C++ Templates: The Complete Guide。第15.1节有关于定义泛型累积类模板的15页以上的讨论。