2

Вопрос по c++, switch-statement, typelist – Тип переключателя во время выполнения для списков типов как переключатель вместо вложенного, если?

Это из TTL:

////////////////////////////////////////////////////////////
//  run-time type switch
template <typename L, int N = 0, bool Stop=(N==length<L>::value) > struct type_switch;

template <typename L, int N, bool Stop>
  struct type_switch
  {
    template< typename F >
      void operator()( size_t i, F& f )
      {
        if( i == N )
        {
          f.operator()<typename impl::get<L,N>::type>();
        }
        else
        {
          type_switch<L, N+1> next;
          next(i, f);
        }
      }
  };

Он используется для переключения типов в TypeList. Вопрос в том, что они делают это через ряд вложенных if. Есть ли способ сделать этот тип переключения в качестве одного оператора выбора вместо?

Спасибо!

Последний Clang может преобразовать такие вещи в таблицу переходов:godbolt.org/g/Nco0AlGCC не может (с такими же параметрами):godbolt.org/g/4VL9e7.

от user877329

Для чего на самом деле используется такая структура?

от Potatoswatter
3 ответа
2

Вам понадобится препроцессор для генерации большого

switch, Тебе понадобитьсяget<> к неоперативным поискам вне границ. Проверьте выходные данные компилятора, чтобы убедиться, что неиспользуемые случаи не дают результатов, если вам это нужно; отрегулируйте по необходимости; v).

Посмотрите Boost Preprocessor Library, если вы хотите добиться успеха в подобных вещах ...

template <typename L>
  struct type_switch
  {
    template< typename F >
      void operator()( size_t i, F& f )
      {
        switch ( i ) {
         #define CASE_N( N ) \
         case (N): return f.operator()<typename impl::get<L,N>::type>();
         CASE_N(0)
         CASE_N(1)
         CASE_N(2)
         CASE_N(3) // ad nauseam.
      }
  };

@UncleBens: Это то, что я имел в виду под "поиском без ограничений". Шаблон typelist сам реализует рекурсию вget<>; он должен обнаружить за пределами индекса и ничего не возвращать. Что касается преимущества над цепью if, это зависит от компилятора и приложения. Согласно ответу на повторяющийся вопрос, Boost :: Вариант (гораздо более известный пример) использует технику, которую я изложил здесь.

от Potatoswatter

Если вы идетедо тошнотыРазве это не значит, что в какой-то момент коммутатор попытается создать экземпляр шаблона с потенциально недопустимым N, и все это не скомпилируется? Рекурсия знает, где остановиться, этот переключатель, очевидно, нет. (По сути, мне кажется, что вся идея переключателя полностью ошибочна, и это не способ метапрограммирования шаблонов. IMO, переключатель времени компиляции - не что иное, как цепочка if, созданная посредством рекурсии.)

от UncleBens

Я просто хочу извиниться за то, что задал почти один и тот же вопрос дважды после вашего ответа. Проблема - я не сразу понял ваш ответ; но теперь, когда я это понимаю, я понимаю, почему мои другие вопросы были излишними.

от anon

@anon: нет, я был драматичным, потому что ситуация была забавной. Можно задавать вопросы тоже ...

от Potatoswatter
0

Я так не думаю.

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

0

Вы всегда можете использовать бинарный поиск вместо линейного поиска.

Это было бы более сложно и с большей вероятностью содержать ошибки (бинарный поиск удивительно легко испортить).

Вы также можете вручную расширить Ntype_switch::operator()где N - это некоторая разумная верхняя граница количества длин списков типов, которые вы будете иметь в своей программе.

Похожие вопросы