'operator *' is ambiguous, how to resolve the ambiguity?
<p>Consider we have a simple mathematical vector class with overloaded <code>operator*</code>.
We overload <code>operator*</code> for scalar multiplication and for inner product as well. It can look like this:</p>

<pre><code>#include &lt;iostream&gt;

template&lt;typename T&gt; struct Vec
{
    template&lt;typename SCALAR_T&gt;
    friend auto operator*(const Vec&lt;T&gt; &amp;v, const SCALAR_T &amp;scalar) 
    {
        return Vec&lt;decltype(T() * SCALAR_T())&gt;{v.x * scalar, v.y * scalar};
    }

    template&lt;typename SCALAR_T&gt;
    friend auto operator*(const SCALAR_T &amp;scalar, const Vec&lt;T&gt; &amp;v)
    {
        return v * scalar;
    }

    template&lt;typename S&gt;
    friend auto operator*(const Vec&lt;T&gt; &amp;v, const Vec&lt;S&gt; &amp;w)
    {
        return v.x * w.x + v.y * w.y;
    }

    T x, y;
};

void templateTest()
{
    Vec&lt;int&gt; vi{ 1, 2 };
    Vec&lt;float&gt; vf{ 2, 3 };
    auto vres = vi * vf;
    std::cout &lt;&lt; vres;
}
</code></pre>

<p>Just as I expected in this case, VS2015 says <code>error C2593: 'operator *' is ambiguous</code>. Compiler cannot choose between function overloads.</p>

<p>The question is: how do I resolve the ambiguity? Ideally I want the 3rd version to be instantiated only for two vector types (<code>Vec&lt;A&gt;</code> and <code>Vec&lt;B&gt;</code>), and for everything else I want scalar version to be used.</p>

<p>Is there a way to use type traits to tell if type is an instantiation of <code>Vec</code> (or not)?</p>

<p>The common solution I've seen in mathematical libraries is to not overload operator* for inner product, but rather use <code>v.dot(w)</code>. This is a solution, but for the sake of theoretical interest, I would love to know how to do this with template metaprogramming.</p>

<p><strong>EDIT:</strong></p>

<p>Okay, the one solution could be to use SFINAE to enable first two overloads only for arithmetic types:</p>

<pre><code>template&lt;typename SCALAR_T, typename = std::enable_if_t&lt;std::is_arithmetic&lt;SCALAR_T&gt;::value&gt;&gt;
friend auto operator*(const Vec&lt;T&gt; &amp;v, const SCALAR_T &amp;scalar) 
{
    return Vec&lt;decltype(T() * SCALAR_T())&gt;{v.x * scalar, v.y * scalar};
}

template&lt;typename SCALAR_T, typename = std::enable_if_t&lt;std::is_arithmetic&lt;SCALAR_T&gt;::value&gt;&gt;
friend auto operator*(const SCALAR_T &amp;scalar, const Vec&lt;T&gt; &amp;v)
{
    return v * scalar;
}
</code></pre>

<p>But this is not an ideal solution, it allows only integral and floating point types as SCALAR_T, but I'd rather want it accept anything other than <code>Vec</code>. So, the question is, how to achieve the following (pseudocode):</p>

<pre><code>template&lt;typename SCALAR_T, typename = std::enable_if_t&lt;not_instantiation&lt;SCALAR_T, Vec&gt;::value&gt;&gt;
</code></pre>