我的问题肯定很愚蠢,但是在我对C ++ 11和模板编程的理解中有很多漏洞,我不知道该如何解决。
我正在滚动自己的非常简单的线性代数库:
typedef short index_t;
template<int M, int N, typename T = double>
class mat {
// may want some specialized constructors for mat<1,N,T> and mat<M,1,T>
public:
T& operator()(index_t i, index_t j) {
return buf[i + j*M];
}
T& operator[](index_t k) { // useful for special cases where matrix is vector
return buf[k];
}
// etc...
private:
std::array<T, M*N> buf;
}
typedef mat<2, 1, double> col2d;
typedef mat<3, 1, double> col3d;
typedef mat<1, 2, double> row2d;
typedef mat<1, 3, double> row3d;
typedef mat<2, 2, double> mat2d;
typedef mat<3, 3, double> mat3d;
我只希望它支持一种直接分配(或至少初始化)向量(即具有单维度的矩阵)的方法。例如,我希望能够执行
v = col2d(v1,v2)
或至少执行col2d v = {v1,v2}
。我的印象是公开buf
可能允许col2d v = {{v1, v2}}
,但是我不喜欢公开buf
的想法。我不希望为每个(1,N)和每个(M,1)编写一个专门的构造函数。我试图使该库尽可能简单易读。有什么建议吗?
最佳答案
mat(std::array<T, M*N>&& buffin):buf(std::move(buffin)){}
mat(std::array<T, M*N> const& buffin):buf(buffin){}
这不会公开
buf
,但是会提供col3d x = {{{ 1,2,3 }}};
语法。它还允许使用平面缓冲区初始化Mat 3d。我自己觉得这很有用。
我可能会想添加
struct flat_t{constexpr flat_t(){};};
constexpr flat_t flat{};
然后在
array
前缀之前加上mat
。这样可以防止意外的隐式转换,同时仍允许flat_t
样式返回。另一个是
template<class...Ts,
std::enavle_if_t< (sizeof...(Ts)==N*M), int> =0
>
mat(flat_t, Ts&&...ts):
buf{{std::forward<Ts>(ts)....}}
{}
这给你
col2d{flat, 1,2};
作为有效的
return {flat, {{1,2,3}}};
。添加一条可将所有
col2d
均可转换为Ts
的sfinae测试是此路径的下一步。