I wrote a simple class for the moving average which can be used with an AVR.
template<typename T, typename Tsum = int32_t>
class MovingAverage { ... }
But now I want to specialize this class for float without copying and pasting the whole class body and change all T and Tsum to float and that I do not need to use two template parameters. Tsum is the type for the 'sum' variable where all passed values of type T were summed up. If T is 'uint8_t' it is a good idea to use 'uint32_t' for the sum, but for float or double there is no need to use a datatype with higher precision, so I want only one parameter for this purpose. I thought it could work this way:
typedef MovingAverage<float, float> MovingAverage<float>
or this way:
template<>
class MovingAverage<float> : public MovingAverage<float, float> {};
But I was wrong and I found only solutions where I have to write my code twice.
Is there a way to write the class only once and then specialize it this way I prefer? Thanks in advance!
If you want different default types for Tsum
, this should be outsourced to another class which can be specified, for example:
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 { ... }
You could write a simple 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.
and then extract this type in your class template
template<typename T, typename Tsum = typename sum_type<T>::type>
// ^^^^^^^^ <-- dependent type disambiguation
class MovingAverage { ... };
Note that this only works if your MovingAverage
has a regularly parameterized implementation. If you are actually doing something special for float
(e.g. rewrite expressions to take care of the non-associative character of floating point arithmetic), then you need to do more work.
If you are serious about working with C++ templates, run -not walk- to the nearest bookstore and get the book C++ Templates: The Complete Guide. Section 15.1 has a 15+ page discussion of defining a generic accumulate class template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With