2014-01-08 79 views
0

我是模板元編程的新手,但我試圖重構一些矩陣操作代碼以提高速度。特別是,現在我的功能看起來是這樣的:如何使用模板元編程重構此循環?

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 d不是模板參數,我肯定會在我的程序中使用不同的大小。所以我想要類似

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

我該如何聲明特定的實例才能使循環終止?提前致謝!

回答

1

不能部分專門的模板功能
但你可以爲模板

以下可以幫助你:

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

大,這個工作只用溫和的性能損失。有什麼特別的原因,我不能部分專門化模板功能? – Andrew

+0

@Andrew:你不能部分地專注於他們 - 幾乎只是因爲語言說你不能。您可以閱讀[爲什麼不專門定製功能模板?](http://www.gotw.ca/publications/mill17.htm)。 – Jarod42