c++ - 如何使用模板元编程重构此循环?

标签 c++ templates metaprogramming

我是模板元编程的新手,但我正在尝试重构一些矩阵操作代码以提高速度。特别是,现在我的函数如下所示:

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 是 #defined 而不是模板参数,我肯定会在我的程序中使用不同的大小。所以我想要类似的东西

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);
}

如何声明特定实例以使循环终止?提前致谢!

最佳答案

您不能部分特化模板函数
但您可以为模板

以下内容可能对您有所帮助:

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;
}

关于c++ - 如何使用模板元编程重构此循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20985919/

相关文章:

c++ - 用于编写 GUI 的通用语言 (C++)

c++ - 在双指针中赋值时出现段错误

c++ - 使用 KDevelop 4.4.1 的 undefined reference

django - 获取模板中的模型字段名称

c++ - 如何在C++模板元编程中返回不止一种类型?

c++ - 如何定义一个函数指针,它采用与给定函数相同的参数和返回值?

c++ - 具有来自不同 header 的模板类的类将无法编译

c++ - 当所有内容都在一个文件中时,为什么我会收到链接器错误?

ruby - 使用什么机制允许从该范围调用 ruby​​ root 范围中定义的方法?

c++ - 有人可以向我解释模板解析顺序规则吗?