2011-05-07 49 views
1

我最近遇到了一种基于数据类型“概念”的调度模式(我认为这是术语概念的正确使用,如果不是,属性??)。Template meta-magic

在我看来,比我之前见过的事情类型更有意义,并且在优化之前至少引入了临时变量和函数调用。我的问题是(1)它是否都实际上得到优化? (2)这是做这种基于类型的调度的“最佳”方式吗?

我正在阅读的代码处理了迭代器类型,所以我将坚持以该模式为例。下面的函数iter_kind接受任何类型的变量并返回特定“概念”类型的虚拟变量。类似于random_access_iterator_kind,或者_Iter是非迭代器类型null_iterator_kind

template <typename _Iter> 
    INLINE_CALL typename iterator_traits<_Iter>::iter_kind iter_kind(_Iter&) 
{ 
    typename iterator_traits<_Iter>::iter_kind _ret; 
    return (_ret); 
} 

它可以通过iterator_traits类的专业化使用通常的元魔。我对所有这些东西感到满意。

iter_kind习惯于委托给特定功能的不同实现,作为一个例子:

template <typename _Iter, typename _Pred> 
    _Iter binary_search(_Iter head, _Iter tail, _Pred pred_less) 
    { 
     binary_search_impl(head, tail, pred_less, iter_kind(head)); 
    } 

template <typename _Iter, typename _Pred> 
    _Iter binary_search_impl(_Iter head, _Iter tail, _Pred pred_less, 
          random_access_iterator_kind) 
    { // actual implementation... 
    } 

template <typename _Iter, typename _Pred> 
    _Iter binary_search_impl(_Iter head, _Iter tail, _Pred pred_less, 
          bidirectional_iterator_kind) 
    { 
     assert(false); // can't do bin search without random access iters!! 
    } 

回答

1

是的,这东西真的都做了优化。编译器是专门编写的,在完成后摆脱这个垃圾,因为这是一个常见的技巧。函数和重载都是这样完成的,因为它比其他任何方式简单得多。这是执行标准库时常用的技巧。

0

哦,不,这不是最好的办法。你可以选择在这样的编译时正确的过载,例如:

template <typename _Iter, typename _Pred>  
    _Iter binary_search(_Iter head, _Iter tail, _Pred pred_less)  
    {   
    binary_search_impl(head, tail, pred_less, 
     std::iterator_traits<_Iter>::iterator_category());  
    } 

更好的方法是在运行时使用SFINAE在实际功能的签名,具有零开销:基本上你会使用std::enable_if在任一迭代器类别上告诉编译器选择哪个超载。

+0

他上面张贴的内容*是标准库的内部工作原理。 – Puppy 2011-05-07 12:17:44