template function definition

Viewed 216

I have this code:

template<typename T1, typename T2>
auto operator*(const T1& a, const T2& b) -> decltype(viennacl::linalg::prod(a, b)) {
    return viennacl::linalg::prod(a, b);
}

template<typename T1, typename T2>
auto operator*(const T1& a, const T2& b) -> decltype(prod(a, b)) {
    return prod(a, b);
}

viennacl::linalg::prod and prod are two different functions (may also be templated).

I thought that if some template function definition can not be used for some types, the compiler would just silently ignore it and try another definition. Is that wrong?

Clang 3.3 compiles fine and all works as expected. GCC 4.9 however throws this error:

mathutils.hpp:77:6: error: redefinition of 'template<class T1, class T2> decltype (prod(a, b)) operator*(const T1&, const T2&)'
 auto operator*(const T1& a, const T2& b) -> decltype(prod(a, b)) {
      ^
mathutils.hpp:72:6: note: 'template<class T1, class T2> decltype (viennacl::linalg::prod(a, b)) operator*(const T1&, const T2&)' previously declared here
 auto operator*(const T1& a, const T2& b) -> decltype(viennacl::linalg::prod(a, b)) {
      ^

So, which compiler is wrong?

And what would be the possible workarounds? (If it is not clear what I want to do: I want to implement operator* so that it uses either viennacl::linalg::prod or prod, depending on which one of those provide an implementation.)


Small self-contained test case:

namespace X {
    template<typename T> struct Mat{};
    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(X::Mat<T> const& A, Mat2 const& B) { return X::Mat<T>(); }


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

template<typename T1, typename T2>
auto operator*(const T1& a, const T2& b) -> decltype(prod(a, b)) {
    return prod(a, b);
}



int main() {}

I reported that upstream as a bug in GCC here.

1 Answers
Related