рекурсия шаблона завершающей функции - PullRequest
3 голосов
/ 24 января 2012

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

#include <iostream>
#include <tr1/tuple>

template<typename tupletype,size_t i>
void print< tupletype ,0>(tupletype t)//error: expected initializer before ‘<’ token
{
    std::cout<<std::tr1::get<0><<" ";
}

template<typename tupletype,size_t i>
void print(tupletype t)
{
    std::cout<<std::tr1::get<i><<" ";// no match for 'operator<<' in 'std::cout << get<-78ul>'(my ide actually hangs here!)
    print<tupletype,i-1>(t);
}

int main (int argc, char * const argv[]) {
    std::tr1::tuple<int,float> a(3,5);
    typedef std::tr1::tuple<int,float> tupletype;
    print<tupletype,0>(a);
}

Ответы [ 4 ]

14 голосов
/ 25 января 2012

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

#include <iostream>
#include <tuple>

template<std::size_t> struct int2type{};

template<class Tuple, std::size_t I>
void print_imp(Tuple const& t, int2type<I>){
  print_imp(t, int2type<I-1>());
  std::cout << ' ' << std::get<I>(t);
}

template<class Tuple>
void print_imp(Tuple const& t, int2type<0>){
  std::cout << std::get<0>(t);
}

template<class Tuple>
void print(Tuple const& t){
  static std::size_t const size = std::tuple_size<Tuple>::value;
  print_imp(t, int2type<size-1>());
}

Живой пример на Ideone .

13 голосов
/ 24 января 2012

Для одного вам нужно объявить шаблон функции перед тем, как его специализовать:

template<typename tupletype,size_t i>
void print(tupletype t);

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

Таким образом, единственный способ сделать то, что вы хотите сделать, это использовать частичную специализацию шаблона класса :

template<typename tupletype,size_t i>
struct printer;

template<typename tupletype>
struct printer< tupletype ,0> {
  static void print(tupletype t)
  {
    std::cout<<std::tr1::get<0>(t)<<" ";
  }
};

template<typename tupletype,size_t i>
struct printer {
  static void print(tupletype t)
  {
    std::cout<<std::tr1::get<i>(t)<<" ";
    printer<tupletype,i-1>::print(t);
  }
};

template<typename tupletype,size_t i>
void print(tupletype t)
{
  printer<tupletype,i>::print(t);
}

Почему быты не хочешь этого делать?

1 голос
/ 24 января 2012

Этот код недействителен.Вы не можете частично специализировать шаблоны функций, которые необходимы для того, что вы хотите сделать.Вам действительно нужна вспомогательная структура.

0 голосов
/ 24 января 2012

У вас есть пара проблем.

Для одной из них вам необходимо объявить шаблон перед тем, как специализироваться.

Для другой вы забыли передать экземпляр типа tupletype в :: get

Однако самое большое - это то, что вы пытаетесь частично специализировать шаблон функции, который не разрешен стандартом (поищите в SO или google, чтобы выяснить, почему).

Теперь нужно решить (несколько)то, что вы просили:

Обратите внимание, что для создания , как правило, полезной рекурсии во время компиляции, вам необходимо создать шаблон входного объекта (т. е. ваш тип кортежа) и индекс, который будет использоваться для рекурсивного использования.перебирать элементы на входе.Для рекурсии шаблона требуется частичная специализация для определения условия выхода.Вы не можете сделать это с помощью шаблонов функций, но вы можете сделать это с помощью классов - следовательно, используйте структуру.

Теперь, в специфическом смысле , вы можете достичь желаемого без использования структур.Для этого вам нужно избегать частичной специализации ... поэтому нам нужно полностью специализироваться.(До того, как за меня проголосовали - я полностью признаю, что это решение не очень полезно в общем смысле - но ОП хотел избежать структур, поэтому я и сделал!)

Сделав так, чтобы функция принимала только определенноеtupletype, мы можем иметь только один параметр шаблона - индекс.Поэтому мы можем полностью специализировать шаблон функции, чтобы получить наше условие выхода:

#include <iostream>
#include <tr1/tuple>

typedef std::tr1::tuple<int,float> tupletype;

template<size_t i>
void print(tupletype t)
{
    std::cout << std::tr1::get<i>(t) << " ";
    print<i-1>(t);
}

template<>
void print<0>(tupletype t)
{
    std::cout << std::tr1::get<0>(t) << " ";
}

int main()
{
    tupletype a(3,5);

    print<1>(a);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...