Глубина создания экземпляра шаблона c ++ превышает максимально 900 - PullRequest
0 голосов
/ 06 сентября 2018

Я использую шаблон c ++ 11 variadic, однако компилятор жалуется, что глубина создания шаблона превышает максимальную 900, код выглядит следующим образом:

template<typename F1, typename F2>
composed<F1, F2> compose(F1 f1, F2 f2) {
    return composed<F1, F2>(f1, f2);
}
template<typename F1, typename F2, typename... Fs>
auto compose(F1 f1, F2 f2, Fs... fs) ->decltype(compose(compose(f1, f2), fs...)) {
    return compose(compose(f1, f2), fs...);
}

Я использую этот шаблон как:

auto composed_func = compose(f1, f2, f3, f4);

Но если я изменю определение шаблона вариа на:

template<typename F1, typename F2, typename F3, typename... Fs>
auto compose(F1 f1, F2 f2, F3 f3, Fs... fs) ->decltype(compose(compose(f1, f2), f3, fs...)) {
    return compose(compose(f1, f2), f3, fs...);
}

Это будет работать нормально. Мне не ясно, почему это произошло. Мне кажется, что верхнее использование также выглядит допустимым, поскольку оно все еще рекурсивно уменьшает аргументы для вызова compose.

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Вы можете исправить это с помощью:

template<typename F1, typename F2>
composed<F1, F2> compose(F1 f1, F2 f2) {
    return composed<F1, F2>(f1, f2);
}

template<typename F1, typename F2, typename... Fs>
auto compose(F1 f1, F2 f2, Fs... fs)
->decltype(compose(::compose(f1, f2), fs...))
{
    return compose(compose(f1, f2), fs...);
}

Демо

ADL может найти неквалифицированные имена, а имя - это поиск в момент создания.

Итак, с неквалифицированным поиском, мы сначала сгенерировали кандидатов (даже если они не будут лучше соответствовать)

compose(f, g) может быть:

  • template<typename F1, typename F2> compose
  • или template<typename F1, typename F2, typename...Fs> compose. (с FS пустой пачкой)

для последующего случая у нас есть decltype(compose(compose(f, g))) для разрешения, и поэтому compose(f, g) снова -> бесконечная рекурсия.

С другой стороны, квалифицированные имена немедленно ищутся, и могут быть найдены только полностью объявленные функции (но не сами по себе, так как конечный тип возврата является частью объявления). поэтому ::compose избегайте считать себя кандидатом перегрузок.

0 голосов
/ 06 сентября 2018

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

template<typename F1, typename F2, typename... Fs>
auto compose(F1 f1, F2 f2, Fs... fs) ->decltype(compose(compose(f1, f2), fs...)) {
    return compose(compose(f1, f2), fs...);
}

Допустим, вы звоните:

compose(f, g, h);

Это вызывает функцию с F1 = decltype(f), F2 = decltype(g) и Fs = {decltype(h)}. Затем функция включается и вызывает:

compose(f1, f2)

что на самом деле:

compose(f, g);

Это вызывает ту же функцию с F1 = decltype(f), F2 = decltype(g) и пустым Fs = {}. В основном выполняет:

compose(compose(f, g));

Что снова вызывает себя с F1 = decltype(f), F2 = decltype(g) и пустым Fs = {}. И это продолжается до бесконечности, или пока не будет достигнут предел 900.

Вам нужно убедиться, что вторая функция актуальна только тогда, когда что-то есть после f2:

template<typename F1, typename F2, typename F3, typename... Fs>
auto compose(F1 f1, F2 f2, F3 f3, Fs... fs) ->decltype(compose(compose(f1, f2), f3, fs...)) {
    return compose(compose(f1, f2), f3, fs...);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...