gpt4 book ai didi

c++ - 基于模板C++创建转置矩阵函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:48:44 26 4
gpt4 key购买 nike

我正在尝试使用这个 amazing guide 创建我的第一个模板,但我遇到了我不知道如何处理多个嵌套参数的麻烦:

我创建的原函数实现如下:

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::vectordouble 甚至可以替换为 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 读作“container holding container holding some small type”,我该如何声明 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确定容器的值类型而不考虑其模板参数,或者它是否是模板,只要它提供 beginend迭代器,或者是 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

关于c++ - 基于模板C++创建转置矩阵函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18848262/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com