我是模板元编程的新手,但我正在尝试重构一些矩阵操作代码以提高速度。特别是,现在我的功能看起来像这样:
template<int SIZE> void do_something(matrix A) {
for (int i = 0; i < SIZE; ++i) {
// do something on column i of A
}
}
我看到一些使用模板重写的技术
#define SIZE whatever
template<int COL> void process_column(matrix A) {
// do something on column COL of A
process_column<COL + 1>(A);
}
template<> void process_column<SIZE - 1>(matrix A) {
return;
}
void do_something(matrix A) {
process_column<0>(A);
}
当我对我的函数执行此操作并将编译器标志设置为适当内联时,我看到了相当不错(~10%)的速度提升。但问题是SIZE #define
不是模板参数,我肯定会在我的程序中使用不同的大小。所以我想要像
template<int COL, int SIZE> void process_column(matrix A) {
// do something on column COL of A
process_column<COL + 1, SIZE>(A);
}
/* HOW DO I DECLARE THE SPECIFIC INSTANCE????
The compiler rightfully complained when I tried this: */
template<int SIZE> void process_column<SIZE - 1, SIZE>(matrix A) {
return;
}
template<int SIZE> void do_something(matrix A) {
process_column<0, SIZE>(A);
}
如何声明特定实例以使循环终止?提前谢谢!
答案 0 :(得分:1)
您不能部分专门化模板功能
但您可以使用模板 class 。
以下内容可以帮助您:
namespace detail {
template<int COL, int SIZE>
struct process_column
{
static void call(matrix& A) {
// do something on column COL of A
process_column<COL + 1, SIZE>::call(A);
}
};
template<int SIZE>
struct process_column<SIZE, SIZE> // Stop the recursion
{
static void call(matrix& A) { return; }
};
} // namespace detail
template<int SIZE> void do_something(matrix& A) {
detail::process_column<0, SIZE>::call(A);
}
C ++ 11的另一种选择:
#if 1 // Not in C++11, but present in C++1y
#include <cstdint>
template <std::size_t ...> struct index_sequence {};
template <std::size_t I, std::size_t ...Is>
struct make_index_sequence : make_index_sequence<I - 1, I - 1, Is...> {};
template <std::size_t ... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
#endif
namespace details {
template <template <std::size_t> class T, std::size_t ... Is, typename ... Args>
void for_each_column_apply(const index_sequence<Is...>&, Args&&...args)
{
int dummy[] = {(T<Is>()(std::forward<Args>(args)...), 0)...};
static_cast<void>(dummy); // remove warning for unused variable
}
} // namespace details
template <template <std::size_t> class T, std::size_t N, typename ... Args>
void for_each_column_apply(Args&&... args)
{
details::for_each_column_apply<T>(index_sequence<N>(), std::forward<Args>(args)...);
}
用法:
class Matrix {};
template <std::size_t COL>
struct MyFunctor
{
void operator() (Matrix&m /* other needed args*/) const
{
// Do the job for Nth column
}
};
int main() {
constexpr SIZE = 42;
Matrix m;
for_each_column_apply<MyFunctor, SIZE>(m /* other args needed by MyFunctor*/);
return 0;
}