【问题标题】:C++ Partial Specialization Not Working for Differing Size Eigen MatricesC++ 部分专业化不适用于不同大小的特征矩阵
【发布时间】:2017-08-15 02:01:42
【问题描述】:

在过去的几个小时里,我一直在努力想弄清楚为什么某些部分模板专业化失败了,我真的可以使用一些帮助。

基本上,我正在编写一些代码,这些代码依赖于在编译时了解矩阵的大小,但我正在尝试使用模板进行通用。使用我真的不明白的类型组合似乎存在某种问题。作为说明,请考虑以下(有点无意义的)代码:

template <typename T> struct type1 { typedef bool bar; };
template <typename T, int R, int C> struct type1<Matrix<T, R, C>> { typedef Matrix<T, R, C> bar; };

template <typename T1, typename T2> struct type2 { typedef bool bar; };
template <typename T, int R, int M, int C> struct type2<Matrix<T, R, M>, Matrix<T, M, C>> { typedef Matrix<float, 2, 2> bar; };

template <typename T1, typename T2> struct type3 { typedef bool bar; };
template <typename T, int R, int M, int C> struct type3<Matrix<T, R, M>, Matrix<T, M, C>> { typedef Matrix<T, R, C> bar; };

template <typename T> struct Test {
    static bool foo() {
        return false;
    }
};
template <typename T, int R, int C> struct Test<Matrix<T, R, C>> {
    static bool foo() {
        return true;
    }
};

我对模板组合的理解是,这些模板应该能够以如下方式组合,其中每一行都应该返回 true。但是请注意,最后两个返回 false。

/* true  <- */  Test<Matrix<float, 2, 2>>::foo();
/* true  <- */  Test<Matrix<float, 6, 3>>::foo();
/* true  <- */  Test<type1<Matrix<float, 2, 7>>::bar>::foo();
/* And so on for any other size . . . */

/* true  <- */  Test<type2<Matrix<float, 3, 3>, Matrix<float, 3, 3>>::bar>::foo();
/* true  <- */  Test<type3<Matrix<float, 2, 2>, Matrix<float, 2, 2>>::bar>::foo();
/* And so on for any other pair of square sizes . . . */

/* false <- */  Test<type2<Matrix<float, 2, 3>, Matrix<float, 3, 2>>::bar>::foo();
/* false <- */  Test<type3<Matrix<float, 2, 4>, Matrix<float, 4, 1>>::bar>::foo();
/* And so on for any other pair of non-square sizes . . . */

特别奇怪的是,当我用任意的 template &lt;typename T, int R, int C&gt; struct Thing 替换 Eigen::Matrix 时,一切都按预期工作(即所有测试都返回 true),这就是为什么我认为这个问题是 Eigen 矩阵特有的。


编辑:实际上,这似乎与我在 MSVC 上构建的事实有关(在 2015 年和 2017 年同样失败)。当我在 g++ 或 clang 上编译它时,它工作正常。更多的证据表明 Visual c++ 是一团糟(并不是真的需要它)。

此外,它似乎实际上与两个参数具有不同大小的情况有关。例如:

template <typename T1, typename T2> struct typetest { typedef bool bar; };
template <typename T, int R1, int C1, int R2, int C2> struct typetest<Matrix<T, R1, C1>, Matrix<T, R2, C2>> { typedef Matrix<float, 2, 2> bar; };

当第一个和第二个矩阵类型具有相同的大小时成功,但当它们不同时失败。例如:

/* true  <- */  Test<typetest<Matrix<float, 2, 3>, Matrix<float, 2, 3>>::bar>::foo();
/* true  <- */  Test<typetest<Matrix<float, 6, 1>, Matrix<float, 6, 1>>::bar>::foo();
/* false <- */  Test<typetest<Matrix<float, 2, 2>, Matrix<float, 2, 3>>::bar>::foo();
/* false <- */  Test<typetest<Matrix<float, 5, 3>, Matrix<float, 2, 4>>::bar>::foo();

不幸的是,由于一些非常烦人的依赖关系,我暂时主要使用 MSVC,所以我需要一个解决方法。有人有什么想法吗?

【问题讨论】:

  • Eigen::Matrix 对我来说一切正常(没有错误值)。我可以给个截图。
  • 顺便用的是最新的3.3.4。
  • 错误信息是?
  • 已经举报,见here
  • 作为一种解决方法,您是否尝试过template &lt;typename T, int R, int C, int O, int Rc, int Cc&gt; struct Test&lt;Matrix&lt;T, R, C, O, Rc, Cc&gt;&gt; {...,即添加Eigen::Matrix 的可选/隐式模板参数? (我没有 MSVC,所以无法测试)

标签: c++ templates matrix metaprogramming eigen


【解决方案1】:

为了使其完整,@chtz 在上面的 cmets 中建议的解决方案完全适用于 MSVC 2015 和 2017。作为与问题不同大小问题的示例,这非常有效:

template <typename T1, typename T2> struct typen { typedef bool bar; };
template <typename T, int R, int M, int C, int O1, int O2, int Rc1, int Rc2, int Cc1, int Cc2>
    struct typen<Matrix<T, R, M, O1, Rc1, Cc1>, Matrix<T, M, C, O2, Rc2, Cc2>> { typedef Matrix<T, R, C> bar; };
...
/* true :-) */  Test<typen<Matrix<float, 2, 3>, Matrix<float, 3, 4>>::bar>::foo();

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    相关资源
    最近更新 更多