您可以使用模板作为模板参数:
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