Rom*_*cer 1 c++ templates c++11
我正在编写一个矩阵类,它是一个模板类:
template <class T, int height, int width>
Run Code Online (Sandbox Code Playgroud)
我想编写计算矩阵行列式的成员函数.如何在不为方矩阵编写完整的单独模板类的情况下,仅为方形矩阵声明此函数?
由于矩阵类是在height和上模板化的,因此width矩阵是一个矩阵,这些模板参数相等.N对于第二个和第三个模板参数,您可以轻松地使用相同的类作为参数:
template <class T, int N>
auto get_det(const Matrix<T, N, N>& mat) -> float;
Run Code Online (Sandbox Code Playgroud)
在您的情况下,这将是最简单的解决方案.但是你也可以这样做enable_if,但在这种特殊情况下它是矫枉过正的.但是,您可以将其应用于其他一些更复杂的解决方案:
template <class T, int H, int W>
auto get_det(const Matrix<T, H, W>& mat) -> std::enable_if_t<H == W, float>;
Run Code Online (Sandbox Code Playgroud)
如果你想了解更多关于SFINAE和的信息,请查看enable_if文档和C++ Idioms/enable-ifenable_if
如果你想要一种方法,不幸的是,事情并不那么容易.您可以专门从一个类中专门设置一个方法,但不能局部专门化它.然而,有一个技巧可以解决它:
template <class T, int H, int W>
struct Matrix {
template <int N = H, int M = W>
auto get_det() const -> std::enable_if_t<N == M, float> { return 2.4f; }
};
Run Code Online (Sandbox Code Playgroud)
你可以像这样测试它:
Matrix<int, 2, 3> not_square;
Matrix<int, 2, 2> square;
// error error: no matching member function for call to 'get_det'
// note: candidate template ignored: disabled by 'enable_if' [with N = 2, M = 3]
//not_square.get_det();
//OK:
square.get_det();
Run Code Online (Sandbox Code Playgroud)
这里get_det需要模板化,因为enbale_if必须对成员模板参数进行操作.否则,如果它将对类模板参数(enable_if_t<H == W>)进行操作,它将禁用整个类,而不仅仅是成员.
一个小缺点是您可以明确地专门化该方法,从而允许在非方形矩阵上调用它.但这是不应该做的事情,通常不是:
// No compilation error:
not_square.get_det<2,2>();
Run Code Online (Sandbox Code Playgroud)
方法的另一个技巧是使用自由函数:
template <class T, int H, int W>
struct Matrix;
namespace detail {
template <class T, int N>
auto get_det(const Matrix<T, N, N>&) -> float { return 3.5; }
}
template <class T, int H, int W>
struct Matrix {
auto get_det2() const -> float { return detail::get_det(*this); }
};
Run Code Online (Sandbox Code Playgroud)
老实说,我认为这不会起作用,但clang和gcc都表现得很好.仍然不是100%肯定它是好的.我有空的时候会调查.