I have a situation where my template modulus operator does play nice between floats and integer-ish types. As I recall there is a way to make it select the more specific one over the broader scope one, but i can't seem to find or remember how to do this.
Basically I have 2 methods which are coliding (redefinition error.)
What I am trying to do is get the specialized modulus operator overload to be used when its the type (T_COORDS) is float, the the broader one when it's not float.
The specialized one (notice it uses the math fmod function):
template <size_t N
, enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0, bool> = false>
friend Coords operator % (const Coords<float,C_COORDS,N_COORDS>& coords0, const auto (& coords1)[N])
{
Coords<float,C_COORDS,N_COORDS> result = coords0;
for (int i=0; i < C_COORDS*N_COORDS; i++)
result.coords[i] = fmod(result.coords[i], coords1[i%N]);
return result;
}
The broader one (notice it uses the standard float modulus):
template <std::size_t N
, std::enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0
, bool> = false>
friend Coords operator % (const Coords<T_COORDS,C_COORDS,N_COORDS>& coords0, const auto (& coords1)[N])
{
Coords<T_COORDS,C_COORDS,N_COORDS> result = coords0;
for (int i=0; i < C_COORDS*N_COORDS; i++)
result.coords[i] %= coords1[i%N];
return result;
}
Those overloads are enclosed with a Template class definition:
template <class T_COORDS, size_t C_COORDS, size_t N_COORDS>
class Coords {
public:
T_COORDS coords[C_COORDS*N_COORDS];
// (body in here)
};
T_COORDS
is a class template parameter, not a function template parameter, which means it makes no difference for partial ordering as the more general function is instantiated with T_COORDS=float
anyway, and so it's exactly the same as the float
one. You can, however, disable that function from overload resolution, utilizing the fact that it already has some enable_if
conditions that are dependent on immediate context:
template <std::size_t N
, std::enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0
&& !std::is_same<T_COORDS, float>{}
// ~~~~~~~~~~~~^
, bool> = false>
friend Coords operator %(const Coords<T_COORDS, C_COORDS, N_COORDS>& coords0
, const auto (& coords1)[N]);