Как использовать тип typename? - PullRequest
2 голосов
/ 09 января 2020

Я новичок в C ++ 11 и пытаюсь написать функцию, способную обрабатывать динамические c типы.

#include <functional>
#include <stdio.h>

template <typename T>
struct scase {
  T param;
  std::function<void(T &&)> pc;
  // typedef T type;
  // or
  // using type = T;
  // ?
};

template <size_t I, typename... T>
void docase(std::tuple<T...> &t) {
  auto sc = std::get<I>(t);

  // using casetype = typename std::tuple_element<I, std::tuple<T...>>::type;
  // typename casetype::type ti;
  // ti = sc.param;
  // sc.pc(ti);
}

template <typename... T>
void select(T &&... cases) {
  auto tuple = std::forward_as_tuple(cases...);
  docase<0>(tuple);
}

int main() {
   select(
     scase<int>{123, [](int &&v) {
       printf("%d\n", v);
     }}
   )
   return 0;
}

Закомментированные коды вызывают ошибки компилятора. Какой правильный синтаксис для этого?

Редактировать:

ошибки, такие как:

error C2825: 'casetype': must be a class or namespace when followed by '::'
error C2510: 'casetype': left of '::' must be a class/struct/union
error C2065: 'type': undeclared identifier
error C2146: syntax error: missing ';' before identifier 'ti'
error C2065: 'ti': undeclared identifier

Ответы [ 2 ]

4 голосов
/ 09 января 2020

Помимо синтаксических ошибок в вашем примере:

casetype является ссылкой, поэтому вы не можете использовать оператор :: для него.

Измените строку на

using casetype = typename std::remove_reference<typename std::tuple_element<I, std::tuple<T...>>::type>::type;

для удаления ссылки.

Живой код здесь .

Также вам необходимо изменить sc.pc() на sc.pc(std::move(ti)), так как Ваша функция ожидает ссылку на rvalue.

Для первого блока комментария: оба способа объявить член typedef действительны, хотя я лично предпочитаю using type = T.

2 голосов
/ 09 января 2020

Это именно тот случай, когда auto значительно облегчает жизнь. Вы можете просто сделать:

template <size_t I, typename... T>
void docase(std::tuple<T...> &t) {
  auto sc = std::get<I>(t);

  auto& ti = sc.param;
  sc.pc(std::move(ti));
}

Если вы хотите, чтобы ti была копией sc.param, вы можете просто опустить ссылку из auto:

template <size_t I, typename... T>
void docase(std::tuple<T...> &t) {
  auto sc = std::get<I>(t);

  auto ti = sc.param;
  sc.pc(std::move(ti));
}

Если вы необходимо иметь отдельное объявление и присваивание, тогда вы можете использовать decltype вместо auto:

template <size_t I, typename... T>
void docase(std::tuple<T...> &t) {
  auto sc = std::get<I>(t);

  decltype(sc.param) ti;
  ti = sc.param;
  sc.pc(std::move(sc.param));
}

Если вам нужно использовать тип несколько раз, вы можете использовать decltype вместе с using :

template <size_t I, typename... T>
void docase(std::tuple<T...> &t) {
  auto sc = std::get<I>(t);

  using casetype = decltype(sc);
  typename casetype::type ti;
  ti = sc.param;
  sc.pc(std::move(sc.param));
}

В качестве альтернативы вы можете просто полностью пропустить ti и передать param непосредственно на sc.pc:

template <size_t I, typename... T>
void docase(std::tuple<T...> &t) {
  auto sc = std::get<I>(t);
  sc.pc(std::move(sc.param));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...