Шаблон мета-магии - PullRequest
1 голос
/ 07 мая 2011

Недавно я столкнулся с неким шаблоном отправки, основанным на «концепциях» типов данных (я думаю, что это правильное использование термина «концепции», если нет, атрибутов ??).

Кажется,для меня, чтобы быть немного более вовлеченным, чем то, что я видел раньше, и, по крайней мере, до оптимизации, вводит временные переменные и вызовы функций.Мой вопрос (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!!
    }

Ответы [ 2 ]

1 голос
/ 07 мая 2011

Да, все это действительно оптимизируется. Компиляторы написаны специально для того, чтобы избавиться от этого мусора после его завершения, потому что это обычная хитрость. Функции и перегрузка этим способом выполняются, потому что, ну, это просто намного проще, чем делать это любым другим способом. Это распространенный прием, используемый при реализации стандартной библиотеки.

0 голосов
/ 07 мая 2011

Ну, нет, это не самый лучший способ. Вы можете выбрать правильную перегрузку во время компиляции, например, так:

 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 для любой категории итераторов, чтобы сообщить компилятору, какую перегрузку выбрать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...