"operator *" is ambiguous, how to resolve ambiguity?

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>>
+4

All Articles