2013-03-03 4 views
6

C++ допускает, чтобы параметры шаблона непигового типа были целыми или перечисляемыми (с интегралом, включающим логическое значение и символ), а также указателями и ссылками на произвольные типы.Использовать случай для параметра шаблона непигового типа, который не имеет интегрального/перечисляемого типа?

Я видел, как широко используются целочисленные, булевые и перечисляемые параметры, и я ценю их полезность. Я даже видел умное использование параметров характера для compile-time parsing of strings.

Но мне интересно, какие существуют варианты использования для параметров шаблона без типа, которые являются указателями или ссылками на произвольные типы?

+3

будет пытаться найти хороший пример, но параметры шаблона указателя функции довольно полезны –

ответ

4

Использование функции-указателя-члена в качестве параметра шаблона позволяет компилятору встроить вызов этой функции. Пример этого использования можно увидеть в моем ответе на этот вопрос: How to allow templated functor work on both member and non-member functions

В этом примере функция-указатель-член в параметре шаблона позволяет генерировать функцию «thunk», которая содержит вызов (inlined) к функции указатель-член. Указатель на функцию thunk имеет общую подпись (и фиксированный размер), которая позволяет хранить и копировать ее с минимальной стоимостью во время выполнения, в отличие от функции-указателя.

+0

Интересно. Я задаюсь вопросом, использует ли это 'std :: bind' или может использовать эту технику. Знаете ли вы, что реализаций 'std :: bind' обычно хранят указатель функции-члена в объекте, возвращаемом, например,' std :: bind (& SomeClass :: some_function, some_arg, _1) '? – HighCommander4

+0

'std :: bind' не может использовать указатель функции-члена как параметр шаблона непигового типа, потому что он принимает указатель на функцию' & SomeClass :: some_function' как параметр функции, а не как параметр шаблона. – willj

+0

Несомненно, но объект, возвращаемый 'std :: bind()', мог иметь указатель на функцию-член как параметр шаблона непигового типа и, следовательно, избегать сохранения указателя функции-члена, правильно? – HighCommander4

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

+0

Я не могу думать ни о чем, наоборот. Объект функции более гибкий, чем синтаксис указателя функции. – Pixelchemist

+0

По-видимому, мне уже достаточно поздно, чтобы я был глуп. Комментарий отозван. – Casey

-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

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; 
Смежные вопросы