我有一个Matrix类模板,如下所示:

template<typename T, std::size_t nrows, std::size_t ncols>
class Matrix
{
    T data[nrows][ncols];
public:
    T& operator ()(std::size_t i, std::size_t j)
    {
        return data[i][j];
    }
};

我想要的是仅在编译时.setIdentity()nrows==ncols时为实例化定义true函数。当.setIdentity()nrows==ncols时,将没有false定义。

我正在尝试使用enable_if惯用法,但这将定义所有情况下的功能。是不是

最佳答案

您可以在以下模式下使用std::enable_if进行操作

template <std::size_t r = nrows, std::size_t c = ncols>
typename std::enable_if<r == c>::type setIdentity ()
 { /* do something */ }

一个完整的例子
#include <type_traits>


template<typename T, std::size_t nrows, std::size_t ncols>
class Matrix
{
    T data[nrows][ncols];

public:
    T& operator ()(std::size_t i, std::size_t j)
    { return data[i][j]; }

    template <std::size_t r = nrows, std::size_t c = ncols>
    typename std::enable_if<r == c>::type setIdentity ()
     { /* do something */ }
};

int main()
 {
   Matrix<int, 3, 3>  mi3;
   Matrix<int, 3, 2>  mnoi;

   mi3.setIdentity();
   // mnoi.setIdentity(); error

  return 0;
}

---编辑---

正如Niall在评论中所指出的(关于TemplateRex的答案,但我的解决方案也存在相同的缺陷),可以通过这种方式来回避此解决方案,以明确显示行数和列数
mi3.setIdentity<4, 4>();

(但这不是一个真正的问题(IMHO),因为mi3是一个方矩阵,并且setIdentity()可以使用实际尺寸(nrowsncols)),甚至可以使用
mnoi.setIdentity<4, 4>()

(这是一个大问题(恕我直言),因为mnoi不是方形矩阵)。

显然有Niall提出的解决方案(添加static_assert;类似
    template <std::size_t r = nrows, std::size_t c = ncols>
    typename std::enable_if<r == c>::type setIdentity ()
     {
       static_assert(r == nrows && c == ncols, "no square matrix");

       /* do something else */
     }

或类似的内容),但我建议在std::enable_if中添加相同的检查。

我是说
template <std::size_t r = nrows, std::size_t c = ncols>
typename std::enable_if<    (r == c)
                         && (r == nrows)
                         && (c == ncols)>::type setIdentity ()
 { /* do something */ }

10-08 11:00