【问题标题】:template function definition模板函数定义
【发布时间】:2014-01-02 04:14:15
【问题描述】:

我有这个代码:

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

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

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::prod 或prod,具体取决于其中哪一个提供了实现。)


小型独立测试用例:

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 中的一个错误。

【问题讨论】:

  • 对于相同的T1和T2,这两种decltype给出的具体类型是什么?如果它们相同,我希望它会像您一样发出消息。
  • prod 和 viennacl::linalg::prod 永远不会同时工作,它总是要么是第一个要么是后者;甚至在这两种情况下都没有定义 decltype 。此外,错误不会在使用时发生,错误在编译器解析定义时已经发生。
  • 您构建 SSCCE 的任何更改?

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


【解决方案1】:

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

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

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

最后,对X::Mat 做了一个小改动,所以我们可以引用它的类型T:

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

这是working test example。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2016-10-19
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多