Перегруженная или шаблонная функция?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Добрый день.

Подскажите какую функцию лучше использовать перегруженную или шаблонную?

С перегруженными кода больно много получается, а шаблонные я не особо люблю, ну или как сказать.

Может кто по опыту своему знает?

sadman41
Offline
Зарегистрирован: 19.10.2016

В абстрактной задаче стоить применить ту функцию, которая больше нравится. Или монетку подкинуть.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Oreshek пишет:

Добрый день.

Подскажите какую функцию лучше использовать перегруженную или шаблонную?

С перегруженными кода больно много получается, а шаблонные я не особо люблю, ну или как сказать.

Может кто по опыту своему знает?

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

например: 

//  Пратотипчег. Функция одна. Вызовы разные

void SendMessage(const int MsgCode = msg_Empty, const int LoParam = 0, const int HiParam = 0);

//  вызывать можно 

SendMessage();
SendMessage(msg_ReadRTC);
SendMessage(msg_Error, Errorcode);
SendMessge(msg_DeviceInitError, Errorcode, ClassID);

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Oreshek пишет:

Подскажите какую функцию лучше использовать перегруженную или шаблонную?

- Подскажите какой автомобиль выбрать - КАМАЗ самосвал  или Мерседес SL родстер?
- А Вам, простите, девочку по набережной покатать или десять кубов навоза перевезти?

Поэтому ответ такой: когда нет никакой задачи, то не нужно использовать ни то, ни другое. А когда появится задача, то она сама подскажет.

-NMi-
Offline
Зарегистрирован: 20.08.2018

ЕвгенийП пишет:

- Подскажите какой автомобиль выбрать - КАМАЗ самосвал  или Мерседес SL родстер?
- А Вам, простите, девочку по набережной покатать или десять кубов навоза перевезти?

Этт ща фсё нипрально, патаму и живём как быдло. Вот раньше девки и в КАМАЗы прыгали и навоз возили и дети нормальные были. А щас? Нищщая страна сабирает в нете деньги на операццию... Тьфу, блеееее.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Спасибо за совет DetSimen.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Случай если что следующий:

void coupArr(byte* array, int sizeArray) {
  sizeArray = sizeArray / array[0];
  uint8_t buf[sizeArray];
  for (uint8_t i = 0; i < sizeArray; i++) {
    buf[i] = array[i];
  }
  for (uint8_t i = 0; i < sizeArray; i++) {
    array[i] = buf[(sizeArray - 1) - i];
  }
}

void coupArr(bool* array, int sizeArray) {
  sizeArray = sizeArray / array[0];
  bool buf[sizeArray];
  for (uint8_t i = 0; i < sizeArray; i++) {
    buf[i] = array[i];
  }
  for (uint8_t i = 0; i < sizeArray; i++) {
    array[i] = buf[(sizeArray - 1) - i];
  }
}

long digByNum(bool* digits, int arraySize) {
  long number = 0;
  for (uint8_t i = 0; i < arraySize / sizeof(digits[0]); i++) {
    number += digits[i];
    number *= 10;
  }
  number /= 10;
  return number;
}

long digByNum(uint8_t* digits, int arraySize) {
  long number = 0;
  for (uint8_t i = 0; i < arraySize / sizeof(digits[0]); i++) {
    number += digits[i];
    number *= 10;
  }
  number /= 10;
  return number;
}
void numByDig(uint8_t data, uint8_t* array) {
  for (uint8_t i = 0; i < UINT8_MAX; i++) {
    array[i] = data % 10;
    data /= 10;
    if (data == 0) {
      return 0;
    }
  }
}

void numByDig(int data, uint8_t* array) {
  for (uint8_t i = 0; i < UINT8_MAX; i++) {
    array[i] = data % 10;
    data /= 10;
    if (data == 0) {
      return 0;
    }
  }
}

void numByDig(long data, uint8_t* array) {
  for (byte i = 0; i < UINT8_MAX; i++) {
    array[i] = data % 10;
    data /= 10;
    if (data == 0) {
      return 0;
    }
  }
}

void printlnArr(uint8_t* array, int sizeArr) {
  for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
    Serial.println(array[i]); 
  }
}

void printArr(uint8_t* array, int sizeArr) {
  for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
	 Serial.print(array[i]);
	 Serial.print(' ');
  }
}

void printlnArr(bool* array, int sizeArr) {
  for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
    Serial.println(array[i]); 
  }
}

void printArr(bool* array, int sizeArr) {
  for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
	 Serial.print(array[i]);
	 Serial.print(' ');
  }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Строки №№ 47, 57 и 67 это про что? С какого бодуна void-функция вздумала чего-то возвращать? Коронавирус подцепила?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Это просто для выхода из функции

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020
void numByDig(uint8_t data, uint8_t* array) {
  for (uint8_t i = 0; i < UINT8_MAX; i++) {
    array[i] = data % 10;
    data /= 10;
    if (data == 0) {
      return;
    }
  }
}

Ну или так..

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

С возвращаемым значением? Оригинально :-)

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Oreshek пишет:

void numByDig(uint8_t data, uint8_t* array) {
  for (uint8_t i = 0; i < UINT8_MAX; i++) {
    array[i] = data % 10;
    data /= 10;
    if (data == 0) {
      return;
    }
  }
}

Ну или так..

 

Вот так уж пойдёт

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Ну или можно просто break применить

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ЕвгенийП пишет:

Строки №№ 47, 57 и 67 это про что? С какого бодуна void-функция вздумала чего-то возвращать? Коронавирус подцепила?

Да там вообще дичь написана. Обратите внимание на строку 2, как вычисляется кол-во элементов в массиве :)))) Слышал звон, называется...

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Что касается сути вопроса - то в данном конкретном примере прям просятся шаблонные функции, имхо.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

DIYMan пишет:

ЕвгенийП пишет:

Строки №№ 47, 57 и 67 это про что? С какого бодуна void-функция вздумала чего-то возвращать? Коронавирус подцепила?

Да там вообще дичь написана. Обратите внимание на строку 2, как вычисляется кол-во элементов в массиве :)))) Слышал звон, называется...

Не, ну а как ещё?

не для себя же)

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020
template <typename Temp>
void coupArr (Temp *array, int size) {
    int count = size;
    for (int i = 0; i < size/2; i++) {
        Temp buff = array[i];
        array[i] = array[--count];
        array[count] = buff;
    }
}

 

 
Вот к стати переписал функцию переворота массива, теперь норм?
DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Oreshek пишет:

теперь норм?

Не совсем. Скажите - бывают массивы с отрицательным числом элементов? А вы в size пихаете int, который знаковый. Надо второй параметр типа size_t использовать, как минимум.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Oreshek пишет:
теперь норм?
При условии, что для типа Temp определена операция "="

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Что за size_t?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Тип данных такой.

Bruzzer
Offline
Зарегистрирован: 17.03.2020

Oreshek пишет:

Что за size_t?

Как уже ответили, это тип данных, но в данном контексте это СКОРЕЕ ВСЕГО троллинг.

b707
Offline
Зарегистрирован: 26.05.2017

Bruzzer пишет:

Как уже ответили, это тип данных, но в данном контексте это СКОРЕЕ ВСЕГО троллинг.

тролинг - это использовать для размера структуры тип int

Bruzzer
Offline
Зарегистрирован: 17.03.2020

Может быть я не прав. Я сегодня впервые увидел size_t. Посмотрел в исходниках - #define __SIZE_TYPE__ long unsigned int. Подумал, что использовать long unsigned int для индекса массива на микропроцессоре - это перебор. Поэтому и написал "СКОРЕЕ ВСЕГО".

Или действительно "Надо второй параметр типа size_t использовать, как минимум."? Основной вопрос к "как минимум"

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Bruzzer пишет:

Посмотрел в исходниках - #define __SIZE_TYPE__ long unsigned int. Подумал, что использовать long unsigned int 

Вы не туда посмотрели. Там много #if и Вы в них запутались. Напечатайте sizeof(size_t) и убедитесь в этом.

Bruzzer
Offline
Зарегистрирован: 17.03.2020

ЕвгенийП пишет:

Вы не туда посмотрели. Там много #if и Вы в них запутались. Напечатайте sizeof(size_t) и убедитесь в этом.

Да вы правы. Для моего UNO значение sizeof(size_t) равно 2.

Но до этого меня заинтересовало - а может ли индекс массива быть отрицательный?

Нашел в инете, что может, проверил в ардуино. Компилируется и работает.

Сначала я думал в сторону - может ли быть отрицательное смещение относительно указателя? Вроде тоже может.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Bruzzer пишет:
может ли индекс массива быть отрицательный?

В принципе может, но Вы сами знаете куда этот путь ведёт.

Не может быть отрицательным только размер, указываемый при объявлении массива, а индекс - это же обыкновенная операция сложения, а операнду операции сложения никто ещё пока не запрещал быть отрицательным.

Bruzzer пишет:
может ли быть отрицательное смещение относительно указателя?

А почему нет? Это же на самом деле никакое не смещение (о чём прямо говорится в стандарте языка) - это просто арифметическая операция вычитания (или сложения с отрицательным) - какие проблемы, почему нет? 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Bruzzer пишет:

Но до этого меня заинтересовало - а может ли индекс массива быть отрицательный?

А я писал где-то про индекс? Я писал про РАЗМЕР массива. и тип данных size_t там - в самую дырочку.

Bruzzer
Offline
Зарегистрирован: 17.03.2020

DIYMan пишет:

А я писал где-то про индекс? Я писал про РАЗМЕР массива. и тип данных size_t там - в самую дырочку.

Это я просто расписывал "полет своей мысли". Постепенно в переписке я отдалился от начального поста.

Я писал, что воспринимаю это как троллинг (в данном контексте - т.е. в адрес новичка), т.к. объявление размера массива как size_t названо КАК МИНИМУМ НЕОБХОДИМЫМ условием.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Bruzzer пишет:

Я писал, что воспринимаю это как троллинг (в данном контексте - т.е. в адрес новичка), т.к. объявление размера массива как size_t названо КАК МИНИМУМ НЕОБХОДИМЫМ условием.

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

Посмотрите для интереса - в STL всё, что касается размерностей - имеет тип size_t. Более того, оператор sizeof c C++ 11 возвращает размер, как тип std::size_t.

Так что - никакого троллинга.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DIYMan пишет:
Более того, оператор sizeof c C++ 11 возвращает размер, как тип std::size_t.

Ещё более того: при описании массива, типа

<тип> massiv [<константа>];

константа всегда преобразуется к std::size_t, а если не может быть преобразована, то это синтаксическая ошибка.

Bruzzer
Offline
Зарегистрирован: 17.03.2020

Лично я узнал что то новое для себя читая этот пост. Но так и не могу понять "как минимум необходимым условием" чего это является. Может это позволит избежать ошибок? Написал простой пример типа

volatile int vInt=0, vInt1=0;
int coupArr (size_t size) {
	cli();		// чтобы оптимизатор функцию не выкинул.
	sei();
	return size;
}
vInt = -1;
vInt1 = coupArr (vInt);

Подумал - может компилятор ругнется на несоответствие типов. Нет не ругнулся. функция приняла -1 и вернула -1. Я не опытный пользователь Ардуино и С++. Может есть ключи компилятора при установке которых он будет показывать ошибки такого рода. Но я, как и все новички, использую настройки по умолчанию. Но даже если проверка и будет происходить, все равно при передаче в функцию указателей на массивы важно (наверное), чтобы передаваемый размер не выходил за границу массива. А это на этапе компиляции не всегда можно проверить. Поэтому и считаю это ТРЕБОВАНИЕ излишним для новичков.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Bruzzer пишет:

 Поэтому и считаю это ТРЕБОВАНИЕ излишним для новичков.

1. Я ничего не требовал;

2. Лучше сразу делать хорошо, херово - оно само получается.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

А как сделать две разные шаблонные функции в одном файле?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020
template <typename T>
void couppArr (T *Arrrray, int size) {
  int count = size;
  for (int i = 0; i < size / 2; i++) {
    T buff = arrrray[i];
    arrrray[i] = arrrray[--count];
    arrrray[count] = buff;
  }
}
void numByDig(T data, T *AArray) {
  for (uint8_t i = 0; i < UINT8_MAX; i++) {
    AArray[i] = data % 10;
    data /= 10;
    if (data == 0) {
      break;
    }
  }
}

Я пробовал так, ни катит.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

и с двумя template <typename> тоже не получается

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Oreshek пишет:

и с двумя template <typename> тоже не получается

В заголовочном файле шаблоны описаны? Давайте код, который "с двумя", и что говорит компилятор. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А Вы что, слово template экономите? Кончаются?

На каждую функцию своё слово template и делайте их хоть 100500.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

ЕвгенийП пишет:

А Вы что, слово template экономите? Кончаются?

На каждую функцию своё слово template и делайте их хоть 100500.

Всм?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

DIYMan пишет:

Oreshek пишет:

и с двумя template <typename> тоже не получается

В заголовочном файле шаблоны описаны? Давайте код, который "с двумя", и что говорит компилятор. 

Заголовочный файл (cpp нет):

#pragma once
#include <Arduino.h>
typedef enum {least, biggest} itemType ;

#define printArr(x) printtArr((x), sizeof((x)))
#define coupArr(v) couppArr((v), sizeof((v)))

template <typename T>
void couppArr (T *Array, int size) {
  int count = size;
  for (int i = 0; i < size / 2; i++) {
    T buff = array[i];
    array[i] = array[--count];
    array[count] = buff;
  }
}
template <typename TT>
void numByDig(TT data, TT *array) {
  for (uint8_t i = 0; i < UINT8_MAX; i++) {
    array[i] = data % 10;
    data /= 10;
    if (data == 0) {
      break;
    }
  }
}

long digByNum(bool* digits, int arraySize) {
  long number = 0;
  for (uint8_t i = 0; i < arraySize / sizeof(digits[0]); i++) {
    number += digits[i];
    number *= 10;
  }
  return number / 10;
}

long digByNum(uint8_t* digits, int arraySize) {
  long number = 0;
  for (uint8_t i = 0; i < arraySize / sizeof(digits[0]); i++) {
    number += digits[i];
    number *= 10;
  }
  return number / 10;
}

uint8_t elementArr(uint8_t* array, int sizeArr, itemType typeElement) {
if(typeElement == biggest) {
  byte largestElement = 0;
  for (byte i = 0; i < (sizeArr / array[0]); i ++) {
    if (array[i] > largestElement) largestElement = array[i];
  }
  return largestElement;
}
}

void printtArr(uint8_t* array, int sizeArr, bool ln = false) {
  if (!ln) {
    for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
      Serial.print(array[i]);
      Serial.print(' ');
    }
    Serial.println();
  } else {
    for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
      Serial.println(array[i]);
    }
  }
}

void printtArr(bool* array, int sizeArr, bool ln = false) {
  if (!ln) {
    for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
      Serial.print(array[i]);
      Serial.print(' ');
    }
    Serial.println();
  } else {
    for (uint8_t i = 0; i < sizeArr / sizeof(array[0]); i ++) {
      Serial.println(array[i]);
    }
  }
}

Слова компилятора:

Arduino: 1.8.12 (Windows 7), Плата:"ATmega328 based, Old bootloader, External 16 MHz, GyverUART [Warning!], AVR-GCC v8.3.0 [Warning!], Enable [Default], Enable [Default], Disable, 2.7V [Default], Disable [Default]"

In file included from S:\Users\AE0E~1\AppData\Local\Temp\arduino_modified_sketch_835342\sketch_apr26a.ino:1:
S:\Users\�������� ����\Documents\Arduino\libraries\array_operation/Array_operation.h: In function 'void couppArr(T*, int)':
S:\Users\�������� ����\Documents\Arduino\libraries\array_operation/Array_operation.h:12:14: error: 'array' was not declared in this scope
     T buff = array[i];
              ^~~~~
S:\Users\�������� ����\Documents\Arduino\libraries\array_operation/Array_operation.h:12:14: note: suggested alternative: 'Array'
     T buff = array[i];
              ^~~~~
              Array
exit status 1
Ошибка компиляции для платы ATmega328 based.

Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, и при чём тут шаблон, если Вы в 9-ой строке пишете Array, а в 12-14 array? Шаблон-то чем виноват?

И, кстати, Вы сообщения компилятора-то читайте - там же прямо так и написано "error: 'array' was not declared in this scope". Что непонятно-то?

И, да, просто кстати, такие конструкции, как у Вас в строке 12 в универсальных шаблонах не пишут, от слова никогда. Ворота тут как-то Пуха в это макал - вот здесь в "ой, блин №1" как раз эта самая ошибка и показана. Посмотрите.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

ЕвгенийП пишет:

просто кстати, такие конструкции, как у Вас в строке 12 в универсальных шаблонах не пишут, от слова никогда. Ворота тут как-то Пуха в это макал - вот здесь в "ой, блин №1" как раз эта самая ошибка и показана. Посмотрите.

Не совсем понял что за ошибка, и как писать надо?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Oreshek пишет:

ЕвгенийП пишет:

просто кстати, такие конструкции, как у Вас в строке 12 в универсальных шаблонах не пишут, от слова никогда. Ворота тут как-то Пуха в это макал - вот здесь в "ой, блин №1" как раз эта самая ошибка и показана. Посмотрите.

Не совсем понял что за ошибка, и как писать надо?

Ключевое для понимания - "operator=", и его отсутствие в типе данных, определённом пользователем.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Oreshek пишет:

Не совсем понял что за ошибка, и как писать надо?

Ну, Вы ссылку-то посмотрели? Программу оттуда запустили? Ругань компилятора видели? Разобрались, чего ему не нравится? Остались вопросы? Или как?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Я не понимаю при чём здесь код из ссылки и как он мне поможет, я спрашивал как правильно написать вот эту конструкцию

template <typename T>
void couppArr (T *array, int size) {
  int count = size;
  for (int i = 0; i < size / sizeof(array[0]); i++) {
    T buff = array[i];
    array[i] = array[--count];
    array[count] = buff;
  }
}

template <typename TT,typename TTR>
void numByDig(TT data, TTR *array) {
  for (uint8_t i = 0; i < UINT8_MAX; i++) {
    array[i] = data % 10;
    data /= 10;
    if (data == 0) {
      break;
    }
  }
}

template <typename TTT>
long digByNumm(TTT* digits, int arraySize) {
  long number = 0;
  for (uint8_t i = 0; i < arraySize / sizeof(digits[0]); i++) {
    number += digits[i];
    number *= 10;
  }
  return number / 10;
}

template <typename TTTT>
uint8_t itemmArr(TTTT* array, int sizeArr, itemType typeItem) {
  TTTT Item = array[0];
  if (typeItem == biggest) {
  for (uint8_t i = 0; i < (sizeArr / array[0]); i ++) {
    if (array[i] > Item) Item = array[i];
  }
	} else if(typeItem == least) {
	for (uint8_t i = 0; i < (sizeArr / array[0]); i ++) {
    if (array[i] < Item) Item = array[i];
  }
	}
	return Item;
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Oreshek пишет:

Я не понимаю при чём здесь код из ссылки и как он мне поможет, я спрашивал как правильно написать вот эту конструкцию

Какую конструкцию? Все 45 строк? Откуда мне знать как её писать правильно, если Вы не сказали что Вы собрались писать?

Я то Вам говорил о гораздо более локальной вещи. Перечитайте пост #41 - я говорил про одну строку (которую Вы так и не исправили. В Вашем нынешнем скетче в строках №№ 5 и 34 ровно та же самая ошибка.

T buff = array[i];

Вот как раз с этой ошибкой Вам и поможет разобраться тот код по ссылке. Там она такая же. Если Вы там доберётесь до библиотеки qwonelib.h, то увидите в строке №20 ровно такую же конструкцию, как у Вас. И там Ворота привёл пример при котором всё это валится нахрен. Смотрите, изучайте, Я не могу изучить за Вас. я это и так знаю.