Reputation: 1881
I have a class-template representing a mathematical vector:
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
// normalize only double/float vectors here
}
private:
// elements in the vector
value_type elements[N];
// the number of elements
static const size_type size = N;
};
I would like to have a special treatment for vectors of integer types, as a vector normalization is not possible on this types. So I need a seperate (may be specialization) for the Normalize method that depends on the template argument Value_T of the VectorT class-template.
I have tried to use template specialization in different ways but did not get it to work. Do I have to make the Normalize function a template function itself? At the moment it just a normal member-method.
Upvotes: 0
Views: 730
Reputation: 48447
You can solve this with a tag dispatching technique:
#include <iostream>
#include <type_traits>
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
using tag = std::integral_constant<bool
, std::is_same<Value_T, double>::value
|| std::is_same<Value_T, float>::value>;
// normalize only double/float vectors here
Normalize(tag());
}
private:
void Normalize(std::true_type)
{
std::cout << "Normalizing" << std::endl;
}
void Normalize(std::false_type)
{
std::cout << "Not normalizing" << std::endl;
}
// elements in the vector
Value_T elements[N];
// the number of elements
static const std::size_t size = N;
};
Upvotes: 3
Reputation: 320371
Yes, you can independently specialize a specific member function of a template class. However, function templates (including member function templates) do not allow partial specializations. Function templates only support explicit specializations. An explicit specialization in your case that would look as follows
// Header file
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
// normalize only double/float vectors here
}
...
};
// Declare an explicit specialization for <int, 5>
template <> void VectorT<int, 5>::Normalize();
and then
// Implementation file
// Define the explicit specialization for <int, 5>
template <> void VectorT<int, 5>::Normalize()
{
...
}
However, explicit initialization is not what you need, apparently, since you want to "fix" the type only and leave the size flexible, i.e. you need a partial specialization. This can be done using the std::enable_if
functionality of C++11 (as shown in other answers) as well as through some basic tricks of C++98.
Of course if your class is relatively lightweight, i.e. it does not have much generic code besides that Normalize
, you can simply partially specialize the whole class. It will take just a bit more typing.
Upvotes: 1
Reputation: 749
Also you can use std::enable_if<>
#include <iostream>
#include <type_traits>
template<class Value_T>
class VectorT
{
public:
template<class T = Value_T>
typename std::enable_if<std::is_integral<T>::value, void>::type
Normalize()
{
std::cout << "Not normalizing" << std::endl;
}
template<class T = Value_T>
typename std::enable_if<!std::is_integral<T>::value, void>::type
Normalize()
{
std::cout << "Normalizing" << std::endl;
}
};
int main()
{
VectorT<int> vint;
VectorT<double> vdouble;
vint.Normalize();
vdouble.Normalize();
return 0;
}
Upvotes: 1
Reputation: 217085
It seems that you want forbid Normalize
for other type than floating point, so you may use static_assert
to have good error message:
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
static_assert(std::is_floating_point<Value_T>::value, "Normalize available only for floating point");
// normalize only double/float vectors here
}
// Other stuff
};
Upvotes: 1