Использование вариативных шаблонов для реализации Get(Tuple) привело к тому, что пакеты параметров не были расширены с ошибкой ‘’

Я хочу реализовать что-то вроде std::get(std::tuple), имея класс кортежа:

template<typename ... Types> class Tuple;
template<> class Tuple<> {};
template<typename First, typename ... Rest>
class Tuple<First, Rest...>: private Tuple<Rest...> {
  First Member;
 public:
  Tuple(const First& first, const Rest& ... rest):
      Tuple<Rest...>(rest...), Member(first) {}

  const First& Head() const {
    return Member;
  }

  const Tuple<Rest...>& Tail() const {
    return *this;
  }
};

Я также реализовал вспомогательную структуру tuple_element.

template<size_t I, class T>
struct tuple_element;

template<size_t I, class Head, class ... Tail>
struct tuple_element<I, Tuple<Head, Tail...> >:
    tuple_element<I - 1, Tuple<Tail...> > {};

template<class Head, class ... Tail>
struct tuple_element<0, Tuple<Head, Tail...> > {
  typedef Head type;
};

Но я не могу понять, как реализовать функцию Get(Tuple). Я думаю, что я пробовал все. Моя последняя попытка:

template<class T, class Head, class ... Tail>
T Get(size_t pos, const Tuple<Head, Tail...>& t) {
  if (pos > 0) {
    return Get<T>(pos - 1, t.Tail());
  }
  return t.Head();
}
template<size_t Pos, class Head, class ... Tail>
typename tuple_element<Pos, Tuple<Head, Tail...> >::type
    Get(const Tuple<Head, Tail...>& t) {
  return Get<typename tuple_element<Pos, Tuple<Head, Tail...> >::type>(Pos, t);
}

Но я получил ошибку: пакеты параметров не расширены с помощью «...»

Что я делаю не так?


person krems    schedule 07.04.2013    source источник
comment
Get<T>(pos - 1, t.Tail()); - Tail здесь тип, который не сработает.   -  person 0x499602D2    schedule 07.04.2013
comment
Спасибо большое! Я счастлив прямо сейчас!   -  person krems    schedule 07.04.2013
comment
Вам нужно использовать либо enable_if, либо специализации шаблона. Первая функция Get возвращает либо T, либо Head в зависимости от условия выполнения — это невозможно.   -  person mfontanini    schedule 07.04.2013


Ответы (1)


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

template<size_t I, class T>
struct TupleElement;

template<size_t I, class Head, class ... Rest>
struct TupleElement<I, Tuple<Head, Rest...> >:
    public TupleElement<I - 1, Tuple<Rest...> > {
  static typename TupleElement<I, Tuple<Head, Rest...> >::Type
      Get(const Tuple<Head, Rest...>& t) {
    return TupleElement<I - 1, Tuple<Rest...> >::Get(t.Tail());
  }
};

template<class Head, class ... Rest>
struct TupleElement<0, Tuple<Head, Rest...> > {
  typedef Head Type;
  static typename TupleElement<0, Tuple<Head, Rest...> >::Type
      Get(const Tuple<Head, Rest...>& t) {
    return t.Head();
  }
};

template<size_t Pos, class Head, class ... Rest>
typename TupleElement<Pos, Tuple<Head, Rest...> >::Type
    Get(const Tuple<Head, Rest...>& t) {
  return TupleElement<Pos, Tuple<Head, Rest...> >::Get(t);
}

Спасибо всем за полезные советы.

person krems    schedule 11.04.2013