C++ 部分专业化不适用于不同大小的特征矩阵
C++ Partial Specialization Not Working for Differing Size Eigen Matrices
在过去的几个小时里,我一直在用头撞墙,试图弄清楚为什么某些部分模板特化会失败,我真的需要一些帮助。
基本上,我正在编写一些代码,这些代码依赖于在编译时了解矩阵的大小,但我正在尝试使用模板来完成它。使用我真的不明白的类型组合似乎存在某种问题。作为说明,请考虑以下(有点毫无意义的)代码:
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;
}
};
我对模板组合的理解是,这些模板应该能够按照下面的方式组合,其中每一行都应该 return 为真。但是请注意,最后两个 return 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 <typename T, int R, int C> struct Thing
替换 Eigen::Matrix
时,一切都按预期工作(即所有测试 return true),这就是我认为这个问题的原因特定于特征矩阵。
编辑:实际上,这似乎与我在 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,所以我需要一个解决方法。有人有什么想法吗?
只是为了使其完整,@chtz 在上面的评论中建议的解决方案完全适用于 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();
在过去的几个小时里,我一直在用头撞墙,试图弄清楚为什么某些部分模板特化会失败,我真的需要一些帮助。
基本上,我正在编写一些代码,这些代码依赖于在编译时了解矩阵的大小,但我正在尝试使用模板来完成它。使用我真的不明白的类型组合似乎存在某种问题。作为说明,请考虑以下(有点毫无意义的)代码:
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;
}
};
我对模板组合的理解是,这些模板应该能够按照下面的方式组合,其中每一行都应该 return 为真。但是请注意,最后两个 return 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 <typename T, int R, int C> struct Thing
替换 Eigen::Matrix
时,一切都按预期工作(即所有测试 return true),这就是我认为这个问题的原因特定于特征矩阵。
编辑:实际上,这似乎与我在 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,所以我需要一个解决方法。有人有什么想法吗?
只是为了使其完整,@chtz 在上面的评论中建议的解决方案完全适用于 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();