基于模板C++创建转置矩阵函数
Create transpose matrix function based on template C++
我正在尝试使用这个惊人的指南创建我的第一个模板,但我遇到了我不知道如何处理多个嵌套参数的麻烦:
我创建的原始函数实现如下:
QVector< QVector<double> > transpose(QVector< QVector<double> > &matrix)
{
int pre_numcols = matrix.size();
int pre_numrows = matrix[0].size();
QVector< QVector<double> > transposed(pre_numrows);
QVector<double> newcols(pre_numcols);
qFill(newcols.begin(), newcols.end(), 0.0);
qFill(transposed.begin(), transposed.end(), newcols);
qDebug()<<transposed.size();
qDebug()<<transposed[0].size();
for (int i = 0; i < pre_numcols; ++i)
{
for (int j = 0; j < pre_numrows; ++j)
{
transposed[j][i] = matrix[i][j];
}
}
return transposed;
}
考虑到我只是重新洗牌,许多类型都是可能的。
QVector
可以被std::vector
取代,double
甚至可以被string
取代。
我走到了这一步:
template<class T>
T transpose(T &matrix)
{
int pre_numcols = matrix.size();
int pre_numrows = matrix[0].size();
T transposed(pre_numrows);
QVector<double> newcols(pre_numcols); // How to do this one?
如果我T
读作"装有某种小类型的容器容器",鉴于它是一个子集,我该如何声明 newcols
变量?
注意:稍后我将编辑qFill()
部分以适应其他情况,例如std::
。
您可以将模板用作模板参数:
template <
template <typename> class Container,
typename ValueType
>
void foo(Container<ValueType> const & c);
因此,您的模板将变为:
template <
template <typename> class Container,
typename ValueType
>
Container< Container<ValueType> > transpose(Container< Container<ValueType> > & matrix)
{
int pre_numcols = matrix.size();
int pre_numrows = matrix[0].size();
Container< Container<ValueType> > transposed(pre_numrows);
Container<ValueType> newcols(pre_numcols);
// ...
return transposed;
}
如果它像那样工作,那就太好了。但是,与现实中一样,新的问题出现了! std::vector
不是template <typename T> class vector
而是
template <
typename T,
typename Allocator = allocator<T>
>
class vector
所以我们必须将我们的函数更改为
template <
template <typename, typename> class C,
typename T,
template <typename> class A = std::allocator,
typename InnerType = C< T, A<T> >,
typename OuterType = C< InnerType, A<InnerType> >
>
OuterType transpose(OuterType & matrix)
{
int pre_numcols = matrix.size();
int pre_numrows = matrix[0].size();
OuterType transposed(pre_numrows);
InnerType newcols(pre_numcols);
// ...
return transposed;
}
这要不那么整洁,我不确定Qt容器是否与此兼容。
既然您说 C++11 可以为您所用,那么您可以使用第一个函数(使用 template <typename> class Container
)并使用标准容器的模板别名:
template <typename T> using vector = std::vector<T, std::allocator<T>>;
vector<vector<int>> v;
auto vprime = transpose<vector>(v);
这是使用辅助模板元函数的另一种可能的解决方案,我认为它比以前的解决方案更干净:
namespace
{
template <typename T> struct get_inner_i {};
template <template <typename> class T, typename Inner>
struct get_inner_i<T<Inner>> { typedef Inner type; };
template <
template <typename, typename> class T,
typename Inner,
template <typename> class Allocator
> struct get_inner_i<T<Inner, Allocator<Inner>>> { typedef Inner type; };
template <typename T> using get_inner = typename get_inner_i<T>::type;
}
template <typename MatrixType>
MatrixType transpose(MatrixType const & matrix)
{
auto const nrows = matrix.size();
auto const ncols = nrows > 0 ? matrix[0].size() : 0;
MatrixType transposed(ncols, get_inner<MatrixType>(nrows));
for(auto k = 0; k < nrows; ++k)
for(auto j = 0; j < ncols; ++j)
transposed[j][k] = matrix[k][j];
return transposed;
}
为什么这个更冗长的解决方案更优越?这不是关于我们必须编写多少代码,而是我们的函数对用户来说有多容易和直观。在此版本中,我们再次只有T
作为模板参数,因此不需要为函数显式指定模板参数。
此外,我们的元函数可以推断它是否是具有自定义分配器参数的容器,用户不必执行上面提到的using
模板别名技巧。
这是另一种解决方案,再次优于以前的解决方案,它使用 std::begin
来确定容器的值类型,而不考虑其模板参数,或者它是否是模板,只要它提供begin
和end
迭代器,或者它是一个 C 样式数组:
namespace
{
template <typename Container>
struct value_type_i
{
typedef typename std::decay<
decltype(*std::begin(std::declval<
Container const &
>()))
>::type type;
};
template <typename Container>
using value_type = typename value_type_i<Container>::type;
}
template <typename MatrixType>
MatrixType transpose(MatrixType const & matrix)
{
auto const nrows = matrix.size();
auto const ncols = nrows > 0 ? matrix[0].size() : 0;
MatrixType transposed(ncols, value_type<MatrixType>(nrows));
for(auto k = 0; k < nrows; ++k)
for(auto j = 0; j < ncols; ++j)
transposed[j][k] = matrix[k][j];
return transposed;
}
您可以在此处看到它的工作原理:http://ideone.com/cCAyFD
- 转置矩阵:交换元素不会更改值
- 使用 Eigen 3 库编写一个带有转置作为参数的函数
- 犰狳(C++)中的快速阵列置换(广义张量转置)
- 为什么转置这个 std::vector<std::vector<std::string> > 这么慢?
- 转置结构容器
- 我的转置矩阵代码有什么问题?
- 数组的转置和乘法
- 在C++中使用矢量转置 2D 矩阵
- 特征:块转置
- MKL矩形矩阵Inplace转置:不使用多个核心
- 并行转置不同的矩阵
- 关于次级对角线的转置(翻转)矩阵
- 输出是从您输入的矩阵中打印出矩阵的转置,但我的代码只是打印出您输入的第一个矩阵
- 如何在阵列火中避免翻转和转置的memcpy?
- CUDA矩阵与共享内存转置
- C 阵列的复合物共轭转置
- 转置期间的动态内存分配
- CImg 转置函数给出错误的宽度
- 我的转置函数有什么问题
- 基于模板C++创建转置矩阵函数