#include <iostream>
using namespace std;

namespace X
{
    template<typename T> struct Mat { typedef T value_type; };
    template<typename T> struct MatExpr {};

    template<typename T>
    MatExpr<T> prod(Mat<T> const& A, Mat<T> const& B) { return MatExpr<T>(); }
}

struct Mat2 {};

template<typename T>
X::Mat<T> prod(const X::Mat<T> &A, const Mat2 &B) { return X::Mat<T>(); }


template<typename T1, typename T2>
auto operator *(const T1 &a, const T2 &b) -> decltype(X::prod(a, b))
{
	cout << __PRETTY_FUNCTION__ << '\n';
    return X::prod(a, b);
}

template<typename T1, typename T2>
auto operator *(const T1 &a, const T2 &b) -> decltype(::prod<typename T1::value_type>(a, b))
{
	cout << __PRETTY_FUNCTION__ << '\n';
    return ::prod(a, b);
}

int main()
{
	X::Mat<int> a, b;
	a * b;
	Mat2 c;
	a * c;
}
