2013-03-03 154 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;