Параметр функции шаблонный класс

Здравствуйте, подскажите пожалуйста как сделать функцию, которая в параметре примет объект шаблонного класса. А конкретно вот что хочу сделать:

Есть библиотека GitHub - GyverLibs/microDS18B20: Легкая и удобная в обращении библиотека для работы с 1-Wire термометрами DS18B20
подключаю у себя ее и создаю две переменных
‘’’
#include <microDS18B20.h>

uint8_t s1_addr = {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE};
uint8_t s2_addr = {0x28, 0xFF, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};

MicroDS18B20<6, s1_addr> sensor1; // Создаем термометр с адресацией
MicroDS18B20<6, s2_addr> sensor2; // Создаем термометр с адресацией
‘’’
Собсно вот в эту функцию нужно передать sensor1 и sensor2 по очереди:
‘’’
int getTemperFromSens(??? sens) {
sens.requestTemp();
if (sens.readTemp()) return sens.getTempInt());
else return 9999; //код ошибки
}
… вызов
int t = getTemperFromSens(sensor1);
‘’’
Ошибку компилятора сейчас не смогу точно скопировать, с другого компа сейчас пишу… но что-то там про template сказано… Я пытался делать так;
int getTemperFromSens(MicroDS18B20& sens) { без амперсанда (по значению) тоже пробовал… в общем ничего у меня не получилось.

А почему с поделием Алекса к нам, а не к нему ???

Здравствуйте, подскажите пожалуйста как сделать функцию, которая в параметре примет объект шаблонного класса. А конкретно вот что хочу сделать:

Есть библиотека GitHub - GyverLibs/microDS18B20: Легкая и удобная в обращении библиотека для работы с 1-Wire термометрами DS18B20
подключаю у себя ее и создаю две переменных
‘’’

#include <microDS18B20.h>

uint8_t s1_addr = {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE};
uint8_t s2_addr = {0x28, 0xFF, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};

MicroDS18B20<6, s1_addr> sensor1; // Создаем термометр с адресацией
MicroDS18B20<6, s2_addr> sensor2; // Создаем термометр с адресацией

‘’’
Собсно вот в эту функцию нужно передать sensor1 и sensor2 по очереди:
‘’’

int getTemperFromSens(??? sens) {
  sens.requestTemp();
  if (sens.readTemp()) return sens.getTempInt());
  else return 9999; //код ошибки
}
… вызов
  int t = getTemperFromSens(sensor1);

‘’’
Ошибку компилятора сейчас не смогу точно скопировать, с другого компа сейчас пишу… но что-то там про template сказано… Я пытался делать так;
int getTemperFromSens(MicroDS18B20& sens) { без амперсанда (по значению) тоже пробовал… в общем ничего у меня не получилось.

Так и думал, что будет с этим проблема)))
Вопрос не по его коду. Если именно с шаблонами это связано… или именно с его шаблонным классом, тогда так и скажите что у меня ничего не получится… не поддерживается Ардуино-языком… Но скорее всего это я дурак, а не Алекс.

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

Понятно. Спасибо! Так и думал, что это я неуч… с шаблонами вообще сам ничего никогда не делал.

Вот его шаблон:

// ====================== CLASS ======================
template <uint8_t DS_PIN, uint8_t *DS_ADDR = (uint8_t*)nullptr, uint8_t DS_AM = 1, bool DS_PGM = 0>
class MicroDS18B20 {
public:
    MicroDS18B20() {
        pinMode(DS_PIN, INPUT);
        digitalWrite(DS_PIN, LOW);
    }
.....

Если не трудно, можете написать заголовок функции с параметром шаблоном:
int getTemperFromSens(<как тут указать шаблон конкретный?> sens);
Если конечно не сложно… :slight_smile: Спасибо :wink:

#include <stdio.h>
#include <stdint.h>


// допустим это класс Гайвера, вам с ним вообще ничего не надо делать
 template <int M>
 class microDS {
 
 public:
      uint16_t a = M;
       
};
    
// а это ваша функция
// делаем ее шаблоном с параметром - тип класса гайвера
template <class T>
void test(T p) {
    printf("a = %d\n", p.a);
 }


microDS<2> P;
microDS<3> K;
    
    
int main()
 {
  printf("Test P ");
  test(P);
  printf("Test K ");
  test(K);
}		

Вывод

Test P a = 2
Test K a = 3

ну если б оно не поддерживалось бы “Ардуино-языком” (кстати, такого нет) - то как бы Гайвер сделал? :slight_smile:

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

1 лайк

Спасибо огромное!. Но что-то мой старый мозг отказывается понимать шаблоны…
Конкретно не могу понять как “мой” шаблон template связывается с шаблоном Гайвера? :frowning:
Неужели через переменные P и K моя функция поймет, что T - microDS? И соответственно в параметре p у меня объект типа microDS и можно пользоваться всеми его полями и методами?

Ну я имел ввиду не сами шаблоны, а параметр в функции. Так как с обычными классами в параметрах без проблем получилось у меня сделать.

Это проверяется в момент компиляции. Если вы подставите вместо класса Т такой, у которого нету нужных полей - ваш код просто не скомпилируется

Или в функцию

template <class T>
void test(T p) {
    printf("a = %d\n", p.a);
 }

можно объект (переменную) любого класса передать у которого есть поле “а”? Тогда как отслеживать ее тип… В общем опять запутался… Ладно… это уже другая история…))) Может и осилю когда нибудь…

Шаблонный класс - тоже не можете.

В итоге имеем:

ХЗ какой код выдаёт ХЗ какую ошибку

От нас-то чего ждёте? Объяснения в чём проблема? Так, ХЗ!

А вообще, не нужен Вам параметр такого типа. Используйте тип auto и не выносите мозги ни себе, ни нам. Компилятор сам разберётся.

In file included from E:\ELECTRONICS\MYPROJECT\MK\ARDUINO\SKETCHS!PUMP\WaterSystem\WaterSystem.ino:42:0:
E:\ELECTRONICS\MYPROJECT\MK\ARDUINO\SKETCHS!PUMP\WaterSystem\Sensors.h:23:36: error: missing template arguments before ‘tSens’
tSens.requestTemp();

Вот такую выдавал.

Многоуважаемый Евгений (без сарказма) можно я сам выберу что мне нужно а что нет. Вы подскажите, а я разберусь. Я понимаю, что у Вас это “безобидные” комментарии, но … мягко говоря выглядят они, будто 90% спрашивающих тут на этом форуме прыщи а вы бог. Да, в какой-то степени это так, Вы действительно очень грамотный в своем деле, но не всем дано быть такими, да и особо не нужно, так зачем явно тыкать в людей пальцем и показывать свое преимущество?.. Многие, в том числе и я, знают прекрасно Вас, что Вы много можете… Ну нельзя же так сильно задирать нос.

Я и код приложил, даже продублировал, потому как в первом сообщении код не выделился, не вставился как положено, и знаю, что тут это грех сильный… поэтому и продублировал, у меня же “тыща” строк… без номеров не разобраться… О боже! И объяснил вроде понятно… ну что Вам всегда нужно всё до бита разложить?
Вроде вежливо обращаюсь, готов ответить на доп вопросы всегда, но в нормальной манере, а не как прыщ с богом общаться.
Это не только к Вам относится, на этом форуме заведено нос задирать. Но, блин, уважение вроде зарабатываете, и на тебе, все рушите… ЗАЧЕМ?

Евгений, не в обиду. Но я постоянно читаю этот форум, иногда задаю вопросы, да под разными именами, бесит ужасно, что ради одного вопроса в год приходится искать пароли… имена… Почему нельзя просто спросить и все, без регистрации… Посмотрите сколько каждый день новичков на форуме… Да это так и происходит, что ради одного вопроса зарегистрируются и все… так почему бы не сделать без регистрации… Но это понятно, что вопрос не к Вам. Это так, к слову :))))
Ладно.

Это почему же??? Опять считаете, что Вы круче, и никто кроме Вас?)))

Мне же пример даже сделали, И я свой код переделал. И все получилось. Да, не совсем понятно все… Но я и не программист по профессии, зачем мне все досконально учить, что бы написать что-то для себя… Да, теперь буду почаще использовать шаблоны, ну и научусь потихоньку… мне торопится некуда, Да и Вам зачем что бы я торопился??? Зачем Вы отправляете все учить с самого нуля? Подскажите по конкретному вопросу и делов, дальше это моя проблема… я не Луну на Луну запускаю, а если Вы думаете, что поможете мне а потом именно так и происходит, что Луна упала по Вашей вине, потому как помогли “кому-то” который возможно тупой, но с Вашей помощью устроился в роскосмос(или куда там) и потом наделал делов… Бога, ради, виной тому кто принимает на работу таких спецов, Ваша то в чем вина? Другой причины я не вижу, почему тут так неохотно помогают с кодом, с примерами…
Ух… Мира и добра всем! Хотя сейчас начнут… повылазят вампиры, будут меня грызть и кусать))))) До и пох)

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

@Ardrunya,

я ведь дал Вам готовое решение Вашей проблемы.

Вы его не заметили, за желанием меня отчитать?

А так, спасибо Вам за отповедь, только вот дёшево передёргивать не надо

Потому, что на момент написание моего комментария Вы НЕ привели кода, НЕ приведи текста сообщения и НЕ привели текста своего шаблонного класса.

Проверьте эти три НЕ, убедитесь, что это так и ответьте сами себе “как Вам можно в таких условиях помочь?”.

Хотите получать адекватные ответы - задавайте адекватные вопросы.

Зря Вы так. Все я видел. Но к этому времени я как раз уже сделал с шаблоном. И посчитал, что так будет правильнее чем с auto… возможно я не прав. Поправьте.

Да вроде написал же, что уже помогли в принципе… И Вам спасибо, я никогда! не оставляю ваших сообщений без внимания. Даже такие, в которых Вы задирая нос чехвостите кого-нибудь но все равно даете, иногда, нужную информацию… Если бы не пример кода выше от B707 я бы конечно попробовал бы auto… Возможно это даже и правильнее в моем случае, но я пока считаю, что с шаблоном я на правильном пути.

Ок. Было у меня:

Спойлер
uint16_t tmrPress, tmrTemp, tmrCurr;
void ReadSens() {
  uint16_t ms = millis();
  if ((uint16_t)(ms - tmrPress) > PERIOD_READ_PRESS_SENS_MS) {
    ReadPress();
    tmrPress = ms;
  }
  if ((uint16_t)(ms - tmrCurr) > PERIOD_READ_CURR_SENS_MS) {
    ReadCurrs();
    tmrCurr = ms;
  }
  if ((uint16_t)(ms - tmrTemp) > PERIOD_READ_TEMP_SENS_MS) {
    ReadTemp();
    tmrTemp = ms;
  }
}

//int GetTemperFromSens(MicroDS18B20 tSens) {
//  tSens.requestTemp();
//}

void ReadTemp() {        //!!!!!!!Переписать, логика тупая и неправильная
  TSens1.requestTemp();  // Запрашиваем преобразование температуры
  TSens2.requestTemp();
  TSens3.requestTemp();
  TSens4.requestTemp();
  bool fErr = false;
  if (TSens1.readTemp()) Heat.t1 = (int)(TSens1.getTemp() * 10);
  else {
    Heat.t1 = 9999;
    fErr = true;
  }
  if (TSens2.readTemp()) Heat.t2 = (int)(TSens2.getTemp() * 10);
  else {
    Heat.t2 = 9999;
    fErr = true;
  }
  if (TSens3.readTemp()) Heat.t3 = (int)(TSens3.getTemp() * 10);
  else {
    Heat.t3 = 9999;
    fErr = true;
  }
  if (TSens4.readTemp()) Heat.t4 = (int)(TSens4.getTemp() * 10);
  else {
    Heat.t4 = 9999;
    fErr = true;
  }

  if (fErr) {
    if (Heat.Err < 250) Heat.Err++;
    return;
  } else {
    if (Heat.Err) {
      if (Heat.ErrCnt <= 250) Heat.ErrCnt++;
      Heat.Err = 0;
    }
  }

  Heat.T = Heat.t1;
  if (Heat.t2 < Heat.T) Heat.T = Heat.t2;
  if (Heat.t3 < Heat.T) Heat.T = Heat.t3;
  if (Heat.t4 < Heat.T) Heat.T = Heat.t4;
}

Стало:

Спойлер
uint16_t tmrPress, tmrTemp, tmrCurr;
void ReadSens() {
  uint16_t ms = millis();
  if ((uint16_t)(ms - tmrPress) > PERIOD_READ_PRESS_SENS_MS) {
    ReadPress();
    tmrPress = ms;
  }
  if ((uint16_t)(ms - tmrCurr) > PERIOD_READ_CURR_SENS_MS) {
    ReadCurrs();
    tmrCurr = ms;
  }
  if ((uint16_t)(ms - tmrTemp) > PERIOD_READ_TEMP_SENS_MS) {
    ReadTemp();
    tmrTemp = ms;
  }
}

template <class TSensTemp>
int GetTemperFromSens(TSensTemp tSens) {
  tSens.requestTemp();
  if (tSens.readTemp()) return (int)(tSens.getTemp() * 10);
  else return 9999;
}

void ReadTemp() {        //!!!!!!!Переписать, логика тупая и неправильная
  bool fErr = false;

  Heat.t1 = GetTemperFromSens(TSens1);
  if (Heat.t1 == 9999) fErr = true;
  Heat.t2 = GetTemperFromSens(TSens2);
  if (Heat.t2 == 9999) fErr = true;
  Heat.t3 = GetTemperFromSens(TSens3);
  if (Heat.t3 == 9999) fErr = true;
  Heat.t4 = GetTemperFromSens(TSens4);
  if (Heat.t4 == 9999) fErr = true;

  if (fErr) {
    if (Heat.Err < 250) Heat.Err++;
    return;
  } else {
    if (Heat.Err) {
      if (Heat.ErrCnt <= 250) Heat.ErrCnt++;
      Heat.Err = 0;
    }
  }

  Heat.T = Heat.t1;
  if (Heat.t2 < Heat.T) Heat.T = Heat.t2;
  if (Heat.t3 < Heat.T) Heat.T = Heat.t3;
  if (Heat.t4 < Heat.T) Heat.T = Heat.t4;
}

Это не конечный вариант, основное, что хотел сделал, осталось причесать окончательно…

Понятно, значит Вы просто ничерта не поняли из того, что я Вам сказал и, вместо того, чтобы спросить, решили отчитать меня.

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

Изучайте
#define printVarLn(x) do { Serial.print(#x "="); Serial.println(x); } while (false)

//
// Класс, который Вы привели (заметьте, ПОСЛЕ моего поста)
//
template <uint8_t DS_PIN, uint8_t *DS_ADDR = (uint8_t*)nullptr, uint8_t DS_AM = 1, bool DS_PGM = 0>
class MicroDS18B20 {
public:
    MicroDS18B20() {
        pinMode(DS_PIN, INPUT);
        digitalWrite(DS_PIN, LOW);
    }

    void kaka(void) {
      printVarLn(DS_PIN);
    }
};

//
// Четыре шаблонных "поросёнка"
// (в реальности поросят было четыре, а не три и волка дожал именно 
// четвёртый, про которого забыли и приписали всё себе - обычная история)
//
MicroDS18B20<5> nif_nif;
MicroDS18B20<6> nuf_nuf;
MicroDS18B20<7> naf_naf;
MicroDS18B20<8> nah_nah;

//
// А вот и функция, которая получает параметром шаблонного поросёнка
// (ради неё и писался пример)
//
inline void printDS(auto & piglet) {
   piglet.kaka();
}


void setup(void) {
   Serial.begin(9600);
   printDS(nif_nif);
   printDS(nuf_nuf);
   printDS(naf_naf);
   printDS(nah_nah);
}

void loop(void) {}

и впредь, если что-то непонятно, спрашивайте, а не отчитывайте собеседника за то, что Вы его не поняли.

P.S.
И, да, кстати, избавьтесь от привычки выкладывать куски кода, которые невозможно просто скопировать и запустить (как Вы это сделали в №20). Резко повысите вероятность подробного ответа. А то у Вас используются ХЗ как описанные переменные и что мне с ними делать? Я же Вам выложил полный код, готовый к запуску. И Вы так всегда поступайте.

4 лайка