2013-03-03 104 views
6

C++允許非類型模板參數爲整型或枚舉類型(帶有包括布爾和字符的整型),以及指向任意類型的指針和引用。非整型/枚舉類型的非類型模板參數的用例?

我已經看到整數,布爾值和枚舉參數廣泛使用,我很欣賞它們的實用性。我甚至見過巧妙使用compile-time parsing of strings的字符參數。

但我想知道什麼是非類型的模板參數的指針或引用任意類型的用例?

+3

將試圖找到一個很好的例子,但函數指針模板參數是非常有用的 – 2013-03-03 21:32:31

回答

4

使用指向成員函數的指針作爲模板參數可以使編譯器內聯對該函數的調用。這個用法的一個例子可以在我對這個問題的回答中看到:How to allow templated functor work on both member and non-member functions

在這個例子中,template參數中的指向成員函數使得能夠生成包含調用的'thunk'函數(內聯)指向成員函數。指向thunk函數的指針具有通用簽名(和固定大小),與指向成員函數的指針不同,它可以以最小的運行時間成本進行存儲和複製。

+0

有趣。我想知道'std :: bind'是否或可以利用這種技術。你知道'std :: bind'實現是否通常在由'std :: bind(&SomeClass :: some_function,some_arg,_1)'返回的對象中存儲成員函數指針? – HighCommander4 2013-07-16 00:27:56

+0

'std :: bind'不能使用成員函數指針作爲非類型模板參數,因爲它將成員函數指針'&SomeClass :: some_function'作爲函數參數,而不是作爲模板參數。 – willj 2013-07-16 16:13:45

+0

當然,但'std :: bind()'返回的對象可以將成員函數指針作爲非類型模板參數,因此避免存儲成員函數指針,對嗎? – HighCommander4 2013-07-16 18:25:06

3

如果您在編譯時知道緩衝區的地址,您可以根據它的對齊方式(在編譯時)做出決定,特別是對於memcpy之類的東西,這樣可以跳過任何運行時檢查,並且直接跳轉到使用最有效大小的類型複製數據。我可能也能夠編譯聲明傳入的指針是頁面對齊的(對於例如nvme協議有用),儘管我不知道那會是什麼樣子。

2

我認爲重要的是指針模板參數是操作。 (其中更間接的方式將是一個函數指針,而「更簡單」的方式一個函數對象[這又是一種試。])

template<typename Key, class Val, bool (*CMP)(Key const&, Key const&)> 
class map 
{ 
}; 

template<typename KEY, class VALUE, typename CMP = std::less<KEY>> 
class map 
{ 
public: 
    CMP cmp; 
}; 

既然你不知道,這比較事先申請,你不能將它建成容器。它需要在外部提供任何需要它的功能或通過模板。

+0

是否存在的任何優勢第一個(函數指針)在第二個(函數對象)? – HighCommander4 2013-07-15 06:11:11

+0

我想不出任何,反之亦然。函數對象比函數指針語法更靈活。 – Pixelchemist 2013-07-15 06:21:30

+0

它顯然只是遲到讓我愚蠢。評論撤回。 – Casey 2013-07-17 07:06:58

-1

以下是非整數模板參數的一個有用示例。有些predeclarations(不是全部,而只是足夠的想法):

template <bool flag, class T, class F> struct SelectType 
{ 
    typedef T Result; 
}; 
template <class T, class F> struct SelectType<false, T, F> 
{ 
    typedef F Result; 
}; 

#define PARAMETER(selector, type) typename SelectType<TypeTraits<T>::selector, type, 

#define PTR_TRAITS typename ::Linderdaum::Utils::TypeTraits<T>::PointeeType 
#define REF_TRAITS typename ::Linderdaum::Utils::TypeTraits<T>::ReferredType 

using namespace ::Linderdaum::Utils; 

template <class T> struct ParameterType 
{ 
    typedef 
    PARAMETER(IsString,   clStringParameter    ) 
    PARAMETER(IsReference,  clPODParameter<REF_TRAITS> ) 
    PARAMETER(IsPointer,  clPointerParameter<PTR_TRAITS>) 
    PARAMETER(IsFundamental, clPODParameter<T>    ) 
    // default 
    clPODParameter<T> 
    >::Result 
    >::Result 
    >::Result 
    >::Result 
    Type; 
}; 

和實際用途代碼:

clParametersList Params; 

ParameterType<const LString& >::Type Param0; 
ParameterType<size_t >::Type Param1; 
ParameterType<clDownloadCompleteCallback >::Type Param2; 

Param0.ReadValue(&P0); 
Param1.ReadValue(&P1); 
Param2.ReadValue(&P2); 

Params.push_back(&Param0); 
Params.push_back(&Param1); 
Params.push_back(&Param2); 
+2

此代碼中的非整型非類型模板參數在哪裏? – HighCommander4 2013-07-16 23:55:07

2

我用的侵入(存儲在數據元素的數據指針)單鏈表之前,這是通過指向數據成員的指針進行參數化的,指示列表存儲鏈接的位置。在參數設置使得它可以存儲在多個列表相同的數據元素,如果他們使用不同的鏈接部件:

template <class T, T* (T::*Link)> class ilist; 

struct Node { 
    Node* a_next; 
    Node* b_next; 
}; 

typedef ilist<Node, &Node::a_next> a_list; 
typedef ilist<Node, &Node::b_next> b_list;