模板函数定义

时间:2013-12-14 11:25:03

标签: c++ templates c++11 g++ clang++

我有这段代码:

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::prodprod是两个不同的函数(也可能是模板化的)。

我认为如果某些模板函数定义不能用于某些类型,编译器会默默地忽略它并尝试另一个定义。这是错的吗?

Clang 3.3编译好,所有工作都按预期进行。然而,GCC 4.9引发了这个错误:

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)) {
      ^

那么,哪个编译器错了?

可能的解决方法是什么? (如果不清楚我想做什么:我想实现operator*,以便它使用viennacl::linalg::prodprod,具体取决于哪一个提供了实现。)< / p>


小型独立测试用例:

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() {}

我报告说上游是GCC中的一个错误here

1 个答案:

答案 0 :(得分:0)

我确信有人会稍后再来,并在标准中引用gcc是对还是错的相关段落。与此同时,您可以尝试以下解决方法:

template<typename T1, typename T2>
auto operator *(const T1 &a, 
                const T2 &b) -> decltype(::prod<typename T1::value_type>(a, b))

我上面所做的是明确指定模板参数,以便它确切知道它应该实例化的prod。另一个微妙之处在于我必须明确地对其进行全局限定,因此ADL不会妨碍它。如果没有这个,编译器会看到anamespace X中的一个类型,并且它最终会同时考虑X::prod::prod,这将是不明确的。

最后,对X::Mat稍作修改,以便我们可以参考其类型T

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

这是working test example