簡體   English   中英

用於非類型模板參數的用例不是整數/枚舉類型?

[英]Use case for non-type template parameter that's not of integral/enumeration type?

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

我已經看到廣泛使用的整數,布爾和枚舉參數,我很欣賞它們的實用性。 我甚至已經看到巧妙地使用字符參數進行字符串的編譯時解析

但我想知道什么是非類型模板參數的一些用例,它們是指針或對任意類型的引用?

使用指向成員函數的指針作為模板參數,編譯器可以內聯對該函數的調用。 在我對這個問題的回答中可以看到這種用法的一個例子: 如何允許模板化仿函數在成員和非成員函數上工作

在此示例中,模板參數中的指向成員函數的指針使得能夠生成包含對指向成員函數的指針的調用(內聯)的“thunk”函數。 指向thunk函數的指針具有通用簽名(和固定大小),這使得能夠以最小的運行時成本存儲和復制它,這與指向成員函數的指針不同。

如果你在編譯時知道緩沖區的地址,你可以根據它的對齊做出決定(在編譯時),特別是對於諸如memcpy之類的東西,這允許你跳過任何運行時檢查,然后直接跳轉到使用最有效的大小類型復制數據。

(我猜)你也可以編譯斷言傳入的指針是頁面對齊的(對於例如nvme協議很有用),雖然我不知道它會是什么樣子。

我認為重要的是,指針模板參數是操作。 (更具間接性的方式是函數指針,以及函數對象“更容易”的方式[反過來又是一種類型。])

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

由於您不知道預先應用哪個比較,因此無法將其構建到容器中。 它需要從外部提供給任何需要它的功能或通過模板提供。

我之前使用了一個侵入式(數據元素中存儲的數據指針)單鏈表,它由一個指向數據成員的指針參數化,指示列表存儲其鏈接的位置。 如果參數化使用不同的鏈接成員,則可以將相同的數據元素存儲在多個列表中:

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;

這是非整數模板參數的有用示例。 一些預先准備(不是全部,但足以得到這個想法):

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM