сдержись instantiation depth exceeds maximum

Делая эксперимент возврата с шаблонами, я прибыл в это:

#include <iostream>
#include <utility>

template< int INDEX = 0 >
void constexpr callInTuple( int index ) {
  if( INDEX == index ) {
    std::cout << INDEX << '\n';
  } else {
    std::cout << "Intentando con " << INDEX << ", fallido\n";
    callInTuple< INDEX + 1 >( index );
  }
}

int main( ) {
  callInTuple( 1 );

  return 0;
}

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

Пробуя с 0, банкрот
1

Но он не составляет даже, показывая ошибку титула:

сдержись instantiation depth exceeds maximum...

Если я это пробую звоня в функцию как

callInTuple( 0 );

Я подождал бы еще более краткий, такой вывод, который я схватил:

0

Однако, я получаю точно ту же ошибку.

  • Что я врежу?

  • Как я это решаю?

6
задан 07.11.2019, 13:04
1 ответ

Мы будем забавляться тем, что будем составителем.


Шаблоны instancian во времени compilaciГіn, когда они заменяют полученные аргументы. HagГЎmoslo: Мы знаем, что callInTuple без parГЎmetros шаблон инстанция с 0, asГ - что должны заменять все INDEX 0, следовательно она funciГіn произведенная:

void constexpr callInTuple( int index ) {
  if( 0 == index ) {
    std::cout << INDEX << '\n';
  } else {
    std::cout << "Intentando con " << INDEX << ", fallido\n";
    callInTuple< 0 + 1 >( index );
  }
}

Работа не закончилась, есть другой призыв к callInTuple с нею expresiГіn 0 + 1, который во времени compilaciГіn переводится в 1, asГ - что должны заменять все INDEX 1, следовательно она funciГіn произведенная он:

void constexpr callInTuple( int index ) {
  if( 1 == index ) {
    std::cout << INDEX << '\n';
  } else {
    std::cout << "Intentando con " << INDEX << ", fallido\n";
    callInTuple< 1 + 1 >( index );
  }
}

, Но мы не закончились, сейчас инстанция callInTuple с нею expresiГіn 2, asГ - что должны заменять все INDEX 2:

void constexpr callInTuple( int index ) {
  if( 2 == index ) {
    std::cout << INDEX << '\n';
  } else {
    std::cout << "Intentando con " << INDEX << ", fallido\n";
    callInTuple< 2 + 1 >( index );
  }
}

, Когда это повторят шестьдесят пять тысяча пятьсот тридцать пять раз (nГєmero может изменять этот segГєn составитель или они parГЎmetros compilaciГіn: -ftemplate-depth) составитель darГЎ из-за побежденный.

Это значит, что ты сделал ее recursiГіn плохо: никогда не достигай базовый случай . У тебя выходит та же ошибка, потому что index - переменная во времени ejecuciГіn в то время как INDEX известен во время compilaciГіn и у составителя нет mГЎs средства защиты, которое должно продолжать производить инстанции callInTuple, потому что у него нет средств, чтобы ломать ее recursiГіn во времени compilaciГіn.

Твои проблемы:

  • , Если базовый случай всегда меньше в переменную ввода, не deberГ-схватывай увеличивать Г-ndice, если не disminuyГ©ndolo.
  • Оба Г-ndices известны во времени compilaciГіn: asГ - которым оба должны быть parГЎmetros не-тип.
  • , Когда встречается базовый случай, ты должен избегать того, чтобы произвелась ветвь, что continГєa с нею recursiГіn: используй if constexpr.

, Предложенные .

#include <iostream>
#include <utility>

template< int START, int INDEX = 0 >
void constexpr callInTuple( ) {
  if constexpr ( INDEX == START ) {
    std::cout << INDEX << '\n';
  } else {
    std::cout << "Intentando con " << START << ", fallido\n";
    callInTuple< START - 1, INDEX >( );
  }
}

int main( ) {
  callInTuple< 1 >( );

  return 0;
}

, Но эта soluciГіn использует условного estГЎtico C ++ 17, когда приклеенный этикетку вопрос, - как C ++ ты не можешь использовать 11, asГ - что deberГ-схвати делать одну especializaciГіn ее plantilla†¦, но они не могут специализироваться частично функционируй шаблон:

template< int START, int INDEX = 0 >
void constexpr callInTuple( ) {
  std::cout << "Intentando con " << START << ", fallido\n";
  callInTuple< START - 1, INDEX >( );
}
// ERROOOOOOR!!
template< int START >
void constexpr callInTuple< START, START >( ) {
  std::cout << START << '\n';
}

AsГ - что она soluciГіn pasarГЎ, из-за того, что классы специализируются:

#include <iostream>
#include <utility>

template< int START, int INDEX = 0 >
struct callInTuple { 
  constexpr callInTuple( ) {
    std::cout << "Intentando con " << START << ", fallido\n";
    callInTuple< START - 1, INDEX >( );
  }
};

template< int START >
struct callInTuple< START, START > {
  constexpr callInTuple( ) {
    std::cout << START << '\n';
  }
};

int main( ) {
  callInTuple< 111, 99 >( );

  return 0;
}

cГіdigo предыдущий производит следующий вывод :

Intentando con 111, fallido
Intentando con 110, fallido
Intentando con 109, fallido
Intentando con 108, fallido
Intentando con 107, fallido
Intentando con 106, fallido
Intentando con 105, fallido
Intentando con 104, fallido
Intentando con 103, fallido
Intentando con 102, fallido
Intentando con 101, fallido
Intentando con 100, fallido
99
5
ответ дан 01.12.2019, 12:27
  • 1
    Jejeje..., что maní в tienes несмотря на то, что использует C ++ 17. Для C ++ 11, без if constexpr( ), и я принимаю ее разом, который я хочу уже :-p –  Trauma 07.11.2019, 14:47
  • 2
    Qué maní в tienes жить в прошлом . –  PaperBirdMaster 07.11.2019, 14:53
  • 3
    Не я... они - мои начальники :-( –  Trauma 07.11.2019, 14:54
  • 4
    Услышь, что я принял ее тебе, но заметил вещь... я нуждаюсь в перемещать один int index как аргумент funció n (не evaluable во времени compilació n). ¿ Ты можешь приспосабливать ответ? –  Trauma 07.11.2019, 18:31
  • 5
    Я могу приспосабливать ответ, чтобы говорить тебе, что то, что ты просишь, не является возможным. ¿ Он стоит тебе? –  PaperBirdMaster 07.11.2019, 18:41

Теги

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