Указатель на функцию с переменным числом аргументов
- Войдите на сайт для отправки комментариев
Втр, 27/08/2019 - 02:10
Ситуация такая, передаю в функцию указатель на функцию.
void function(){
EEPROM.put(0,var);
}
void millisTimer(uint32_t &previousTime, uint32_t interval,
void (*function)())
{
if (millis() - previousTime > interval)
{
previousTime = millis();
function();
}
}
millisTimer(previousTime, 1000, function);
Так работает замечательно, но если я передаю напрямую EEPROM.put(0,var); валятся ошибки.
Пробовал через шаблон то же не получаеться.
template <typename T, typename... ArgTypes>
void millisTimer(uint32_t &previousTime, uint32_t interval,
Т (*function)(ArgTypes... arg))
{
if (millis() - previousTime > interval)
{
previousTime = millis();
function();
}
}
millisTimer(previousTime, 1000, EEPROM.put(0,var));
Так же с ошибками. Помогите разобраться.
Здесь надо лямдофункцию организовывать
И как же Вы это делаете? Секрет?
Памойму, это не адрес функции, а её вызов в этом месте.
Ну, скетча мы не видели, а потому, хрен его знает что там.
Var любого типа в том числе и структура.
Про лямдафункцию вчера начал читать, но поздно уже было. Сегодня продолжу изучение.
Уже начинаю понимать природу ощибок.
Действително я вызываю функцию, а не передаю.
Нужно делать как то так:
А вот как обработать передаваемые параметры и вставить их в функцию для меня пока загадка.
Видимо нужно копать в сторону загадочных лямбда функций.
самое страшноя, что EEPROM.put - сама есть шаблонная функция.
А что в этом страшного если не секрет?
Не, если ты знаешь, как правильно передавать в функцию указатель на другую, шаблонную функцию с двумя параметрами - то ничего страшного. Но мой кругозор настока не простирается. Поделись потом кодом, если удасца.
Нужно делать как то так:
Нет, так делать не нужно. С шаблонами так не работают.
Если бы мой кругозор был настолко велик не было бы данной темы. Поэтому и обратился за помошью.
Нужно делать как то так:
Нет, так делать не нужно. С шаблонами так не работают.
а как нужно делать?
Пришол вот к такому виду.
template <typename T, typename... Args> T millisTimer(uint32_t &previousTime, const uint32_t interval, T (*function)(), Args&... args);Но если пытаюсь передать параметры все равно ошибки.
И да же если не шаблонную функцию передовать все равно не получаеться.
Немного нашел информации:
https://docs.microsoft.com/ru-ru/cpp/cpp/lambda-expressions-in-cpp?view=vs-2019
https://docs.microsoft.com/ru-ru/cpp/cpp/ellipses-and-variadic-templates?view=vs-2019
Вот кусок кода как пример что я хочу получить.
#include <iostream> using namespace std; void print() { cout << endl; } template <typename T> void print(const T& t) { cout << t << endl; } template <typename First, typename... Rest> void print(const First& first, const Rest&... rest) { cout << first << ", "; print(rest...); // recursive call using pack expansion syntax } int main() { print(); // calls first overload, outputting only a newline print(1); // calls second overload // these call the third overload, the variadic template, // which uses recursion as needed. print(10, 20); print(100, 200, 300); print("first", 2, "third", 3.14159); }Забудем навсегда про EEPROM.put
Цель стоит не переписывать каздый раз конструкцию с millis().
if (millis() - previousTime > interval) { previousTime = millis(); myFunction(args); }А вынести ее в отдельную функцию передать предыдущее значение millis(), интервал и функцию которая дожна выполниться.
Все хорошо работает с void или когда известно число и тип аргументов функции.
template <typename T> T millisTimer(uint32_t &previousTime, const uint32_t interval, T (*function)(int), int a);Но когда у нас множество функций с разными типами и разным количеством аргументов работать ни чего не хочет.
а как нужно делать?
Для начала Вы попытайтесь внятно объяснить ЧТО нужно делать, а потом уже поговрим "как". Сначала Вы скзали, что надо передавать указатели на функции с переменным числом параметров, потом, что это должны быть шаблоны, потом уж лямбды - что будет в следующем посте?
Вы можете внятно и спокойно объяснить что нужно сделать. Не предлагать свои решения, а просто сказать "что"?
Пришол вот к такому виду.
Давайте, я не будe комментировать :)
Если бы мой кругозор был настолко велик не было бы данной темы. Поэтому и обратился за помошью.
Немного нашел информации:
Забудьте про лямбды. Ибо "если бы Ваш кругозор был настолко велик", Вы бы могли их использовать, а так - забудьте. Вы даже не знаете для чего они нужны, ну и чего суётесь в воду, не зная броду?
Вот кусок кода как пример что я хочу получить.
Ну, и где в этом коде передача указателя на функцию? Ещё раз, к началу моего поста, объясните наконец внятно, что же Вам нужно-то? Только внятно, словами, а не примерами и, Боже упаси, без Ваших идей готовых решений на лямбдах, шаблонах, или ещё на чём.
Пост выше я написал, что хочу получить.
И если не затруднит коментируйте ;)
template <typename T> T millisTimer(uint32_t &previousTime, const uint32_t interval, T (*function)(int), int a);Но когда у нас множество функций с разными типами и разным количеством аргументов работать ни чего не хочет.
Так Вы чего пишете? Вы хотите, как я понял, написать шаблон для любого типа указателя на функцию, а пишете для любого возвращаемого функцией значения (да ещё и весь millisTimer почему-то этот же тип возвращает).
Вы пытаетесь использовать шаблоны как мартышка очки. Угадал? Не выйдет, читайте нормальную литературу про шаблоны. Без понимания там трудно.
Ладно, сейчас я убегаю, вернусь в сеть вечером, попрбуйте пока понять что такое Т в Вашей записи и внимательно читайте в моём предыдущем посте что именно Вы на самом деле сделали.
Ну а я, как неугадавшый, самоудалюся
anarch, ну как вам наш местный Моисей(ЕвгенийП) . С такими проводниками вы или 40 лет будете ходить до земли обетованой. Или выведет вас вместо Одессы на Херсон.
Вы изначально взяли не тот инструмент для решения задачи, только и всего. Решать надо через лямдафункции. Но новичкам их не предлагают. Дедовщина она и на форуме дедавщина.:(
/**/ #include <EEPROM.h> typedef void (*pDo)(); void millisTimer(uint32_t &previousTime, uint32_t interval, pDo Do) { if (millis() - previousTime > interval) { previousTime = millis(); Do(); } } unsigned long previousTime = 0; unsigned long previousTime1 = 0; int var = 12; void setup() { Serial.begin(9600); } void loop() { millisTimer(previousTime, 1000, [] {EEPROM.put(0, var);}); millisTimer(previousTime1, 1000, [] {Serial.println("Tuc");}); }ПС: Просто иногда контрабандой из под полы предлагаю.Последнюю отдал.
Сдается мне что это не совсем то, что хочет в #11.
Надо в таймере на миллисе вызывать ф-ции с произвольным кол-вом аргументов, а тут в стр.7 вобще без аргумента. Понятно что сунув туда обертку на функцию с аргументами можна выкрутится через глобальные, как в стр.17 var сделана. Но наверно это не очень. У лямд там в [] можна койчего писать еще ;) может так пройдет.
Я бы шото такое пробовал. Собирается но передачу данных в Fn сами проверяйте.
int Fn(...){Serial.print("Fn"); return 6;} uint32_t previousTime; template <typename T, T (*func)(...)> T millisTimer(uint32_t &previousTime, uint32_t interval, ... ) { if (millis() - previousTime > interval) { previousTime = millis(); va_list arg_ptr; va_start(arg_ptr, interval); func(arg_ptr); va_end(arg_ptr); } } void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: uint32_t previousTime = millis(); millisTimer<int, Fn>(previousTime, 1000, 1,2); millisTimer<int, Fn>(previousTime, 1000, 1,2,3,4); }Вобще довольно симпатично выходит, если еще вместо функции класс передавать и в него засунуть его личный статический previousTime то совсем прикольно.
qwone, Logik, огромное спасибо!
Но код от qwone более безопасен. Теперь понял, что не в том направлении двигался ;)
Если я все правилно понимаю в лябда функции можно выполнять кусок кода?
Для примера проверять линк:
millisTimer(previousTime, 1000, [] { if (Ethernet.linkStatus() == LinkOFF) { Serial.println("Ethernet cable is not connected."); } });А что если я захочу, что бы millisTimer возращала что нибудь.
[] {return myFunc();}Натолкните в какой сторону изучать.