模板元魔法

Template meta-magic

本文关键字:      更新时间:2023-10-16

我最近遇到了一种基于数据类型"概念"的调度模式(我认为这是术语概念的正确用法,如果不是,属性??

在我看来,它比我以前见过的事情要复杂一些,至少在优化之前,引入了临时变量和函数调用。我的问题是(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!!
    }

是的,这些东西确实都被优化了。编译器是专门为在完成后摆脱这种污垢而编写的,因为这是一个常见的技巧。以这种方式完成函数和重载是因为,嗯,它比任何其他方式都容易得多。这是标准库实现中使用的常用技巧。

嗯,不,这不是最好的方法。您可以在编译时选择正确的重载,例如:

 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 来告诉编译器要选择哪个重载。

相关文章:
  • 没有找到相关文章