#c #templates #c 14
#c #шаблоны #c 14
Вопрос:
Мне нужна шаблонная функция, которая проверяет, есть ли первое значение среди последующих.
Я думал, что попробую что-то подобное, но это не сработало
template<class T, class U>
bool is_in_set(const T amp;t, const U amp;u) {
return t == u;
}
template<class T, class ...Args>
bool is_in_set(const T amp;t, Args...args) {
return false || is_in_set(t, args...);
}
Он компилируется, но я получил следующее предупреждение warning C4717 : 'is_in_set' : recursive on all control paths, function will cause runtime stack overflow
Кто-нибудь может помочь мне исправить это и объяснить, почему это не работает?
Комментарии:
1. Что вы подразумеваете под «это не работает»? Если он не компилируется, покажите сообщение об ошибке. Если он запускается, но выдает неверный вывод, покажите ввод и вывод.
2. Он компилируется, но я получил предупреждение о том
warning C4717 : recursive on all control paths, function will cause runtime stack overflow
, что я попытался запустить проблему, но произошло переполнение3. Спасибо, но, пожалуйста, добавьте эту информацию в вопрос, а не в качестве комментария.
Ответ №1:
Начиная с C 17, вы можете написать эту функцию с помощью fold-выражения, что проще, чем писать рекурсивную функцию с базовым вариантом.
template<class T, class ...Args>
bool is_in_set(T const amp; t, Args const amp; ...args)
{
return (... || (t == args));
}
И теперь вы можете назвать это так.
is_in_set(1, 2, 3, 4); // false
is_in_set(1, 2, 1, 4); // true
Вот демонстрация
Учитывая ваш код, вы получаете предупреждение, потому что у вас бесконечная рекурсия в этой строке:
return false || is_in_set(t, args...); // infinite recursion here
Обратите внимание, что вы вызываете шаблон функции рекурсивно с точно такими же аргументами. Это означает, что вы будете повторять бесконечно и никогда не достигнете базового варианта.
Вы можете исправить это, присвоив второму аргументу имя и приняв остальные аргументы в качестве пакета параметров.
template<class T, class U>
bool is_in_set(T const amp; t, U const amp;u)
{
return t == u;
}
template<class T, class U, class ...Args>
bool is_in_set(T const amp; t, U const amp; u, Args const amp;...args)
{
return is_in_set(t, u) || is_in_set(t, args...);
}
Вот демонстрация
Комментарии:
1. Я работаю на c 14 в Visual Studio
2. @Linus Да, я только что увидел это, когда редактировал теги, поэтому я мог бы обновить ответ. Могу я спросить, почему вы все еще используете этот стандарт? Есть ли какие-либо внешние ограничения? Если нет, просто обновите свой компилятор.
3. На самом деле нет причин, это была настройка по умолчанию, я не так много знаю о разнице в стандарте, я попробую
4. Я не могу поверить, что это работает, я провел последние 2 дня, пытаясь понять это, что мне ввести, чтобы прочитать что-нибудь о 3 точках?
5. @Linus Отлично 🙂 Вы получите кучу дополнительных функций, которые можно использовать, если вы используете более современный стандарт, такой как C 17 или даже C 20. Я добавил решение, которое в любом случае работает и на C 14.
...
Синтаксис представляет собой сложенное выражение. Я добавил ссылку для дальнейшего чтения.