2016-04-28 25 views
2

我寫了一個模板化的Matrix結構,它通過使用地圖在內部抽象連續索引。如何簡化模板化回調函數的定義?

Matrix<TCell, TKey> m; 

有擴大結構的功能,我想給用戶傳遞一個函數指針(initFunc)填充新創建的細胞的能力。現在

void ExpandMatrix(Matrix<TCell, TKey>* matrix, 
         std::set<TKey>* keys_c, 
         std::set<TKey>* keys_r, 
         ??? /*Function pointer to callback function */ 
        ) 

我的問題是,這個用戶提供的函數需要傳遞一個指針,以及細胞,沒有任何內部計數器我用的鑰匙。這些通過模板定義爲TCellTKey。所以我不能用這個,因爲它還不知道究竟TCellTKey是:

typedef void (*initFunc)(TCell* pCell, TKey key_c, TKey key_r) 

至於我的研究去,它是不可能的模板函數指針:

template<typename TCell, typename TKey> 
typedef void (*initFunc)(TCell* pCell, TKey key_c, TKey key_r) 

什麼我目前的做法是將該功能包裝在用戶認爲可以派生的類中,但這對用戶來說很麻煩。沒有更好的解決方案嗎?

template <typename TCell, typename TKey> 
class DefaultCellInitializer 
{ 
    public: 
    virtual void Initialize(TCell* t, TKey key_c, TKey key_r) 
    { 
     return; 
    } 
}; 

template<typename TCell, typename TKey> 
void ExpandMatrix( Matrix<TCell, TKey>* matrix, 
        std::set<TKey>* keys_c, 
        std::set<TKey>* keys_r, 
        CellInitializer<TCell, TKey> initializer = DefaultCellInitializer) 

注意:我需要允許一個默認值,它無法處理傳統方法的使用。歡迎使用C++ 11,但必須在MSVC 2012上進行編譯。由於政治原因,Boost尚未成爲一種選擇。

回答

3

您不需要typedef模板函數指針。你可以定義ExpandMatrix()參數類型爲直接函數指針:

template<typename TCell, typename TKey> 
void ExpandMatrix(Matrix<TCell, TKey>* matrix, 
        void (*initFunc)(TCell*, TKey, TKey) = defaultCellInitializer) {} 

defaultCellInitializer()可能是

template<typename TCell, typename TKey> 
void defaultCellInitializer(TCell* pCell, TKey key_c, TKey key_r) { 
    ... ... 
} 

LIVE

+0

好的,我很習慣於用typedef定義外部的函數指針,這是我從未想到的。要嘗試它,看起來很有前景 – antipattern

2

你可以使用這些模板類型使用std::function。這可以綁定到lambda。

template <typename TCell, typename TKey> 
void ExpandMatrix(Matrix<TCell, TKey>* matrix, 
        std::set<TKey>* keys_c, 
        std::set<TKey>* keys_r, 
        std::function<void(TCell*, TKey, TKey)> callback 
       ); 

然後拉姆達:

ExpandMatrix(/* args */, [](/* type list for arguments */) { 
    /* implementation */ 
    }); 

當您綁定的拉姆達爲std::function,則需要在所需參數列表提供類型。

如果您不僅限於lambda,還可以使用函數指針。

此外,std::function可以替換爲自己的模板參數,並以與標準庫在其算法中使用謂詞相同的方式使用(例如std::find_if);

template <typename TCell, typename TKey, typename Callback> 
void ExpandMatrix(Matrix<TCell, TKey>* matrix, 
        std::set<TKey>* keys_c, 
        std::set<TKey>* keys_r, 
        Callback callback 
       ); 

此外,callback可以綁定到函數指針,函子,lambdas等。

+0

看起來很有希望,但我更喜歡簡單的函數指針,因爲std :: function的開銷。如果@宋遠堯的建議沒有成功,我會走你的路線。 – antipattern

+0

開銷應該很小,但在那裏。你可以把它作爲一個模板參數本身,就像標準庫在標準算法中使用謂詞等一樣,例如'find_if'等。 – Niall

+0

我不想用這個語句來貶低你的建議。 – antipattern