Consider that we have a simple mathematical vector class with overloaded operator*. We overload operator*for scalar multiplication and for the domestic product. It might look like this:
#include <iostream>
template<typename T> struct Vec
{
template<typename SCALAR_T>
friend auto operator*(const Vec<T> &v, const SCALAR_T &scalar)
{
return Vec<decltype(T() * SCALAR_T())>{v.x * scalar, v.y * scalar};
}
template<typename SCALAR_T>
friend auto operator*(const SCALAR_T &scalar, const Vec<T> &v)
{
return v * scalar;
}
template<typename S>
friend auto operator*(const Vec<T> &v, const Vec<S> &w)
{
return v.x * w.x + v.y * w.y;
}
T x, y;
};
void templateTest()
{
Vec<int> vi{ 1, 2 };
Vec<float> vf{ 2, 3 };
auto vres = vi * vf;
std::cout << vres;
}
As I expected in this case, VS2015 says error C2593: 'operator *' is ambiguous. The compiler cannot choose between function overloads.
Question: how can I eliminate the ambiguity? Ideally, I want the 3rd version to be created for only two types of vectors ( Vec<A>and Vec<B>), and for everything else I want to use the scalar version.
Is there a way to use type attributes to determine if a type is an instance Vec(or not)?
, , * , v.dot(w). , , , , .
EDIT:
, SFINAE :
template<typename SCALAR_T, typename = std::enable_if_t<std::is_arithmetic<SCALAR_T>::value>>
friend auto operator*(const Vec<T> &v, const SCALAR_T &scalar)
{
return Vec<decltype(T() * SCALAR_T())>{v.x * scalar, v.y * scalar};
}
template<typename SCALAR_T, typename = std::enable_if_t<std::is_arithmetic<SCALAR_T>::value>>
friend auto operator*(const SCALAR_T &scalar, const Vec<T> &v)
{
return v * scalar;
}
, SCALAR_T, , -, Vec. , , ():
template<typename SCALAR_T, typename = std::enable_if_t<not_instantiation<SCALAR_T, Vec>::value>>