C ++允许非类型模板参数为整数或枚举类型(包括布尔和字符的整数),以及指向任意类型的指针和引用。
我已经看到广泛使用的整数,布尔和枚举参数,我很欣赏它们的实用性。我甚至已经看到compile-time parsing of strings的字符参数的巧妙使用。
但是我想知道作为指针或对任意类型的引用的非类型模板参数的一些用例是什么?
答案 0 :(得分:4)
使用指向成员函数的指针作为模板参数,编译器可以内联对该函数的调用。我在这个问题的答案中可以看到这种用法的一个例子:How to allow templated functor work on both member and non-member functions
在这个例子中,模板参数中的指向成员函数的指针使得能够生成一个&th; thunk'包含对指向成员函数的指针的调用(内联)的函数。指向thunk函数的指针具有通用签名(和固定大小),这使得能够以最小的运行时成本存储和复制它,而不像指向成员函数的指针。
答案 1 :(得分:3)
如果你在编译时知道缓冲区的地址,你可以根据它的对齐做出决定(在编译时),特别是对于诸如memcpy之类的东西,这允许你跳过任何运行时检查,只是直接跳转到使用最有效大小的类型复制数据。
(我猜)你也可以编译断言传入的指针是页面对齐的(对于例如nvme协议很有用),虽然我不知道它会是什么样的。
答案 2 :(得分: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;
};
由于您不知道预先应用哪个比较,因此无法将其构建到容器中。它需要从外部提供给任何需要它的功能或通过模板。
答案 3 :(得分: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;
答案 4 :(得分:-1)
以下是非整数模板参数的有用示例。一些预先准备(不是全部,但只是足以得出这个想法):
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 );