Dans un message précédent, je jouais avec les template pour écrire des méthodes génériques dans une classe. template <typename T>
Cependant, j'aimerais connaitre le type utilisé effectivement dans la fonction lorsqu'elle est compilée (ou exécutée). Par exemple, savoir si le type est signé ou non signé.
Je veux pouvoir générer des nombres aléatoires entre une valeur min et une valeur max, mais je veux avant cela vérifier si les bornes sont compatibles du type employé (pas de négatif si non signé, pas de dépassement de valeur maximale).
Or le type est générique lorsque j'écris ma fonction... Donc comme savoir si le type est signé, ou connaitre les valeurs min et max de mon type dans le code de ma fonction ?
Merci
Oui, mais (car le corollaire, c'est "il y a toujours un mais" ) :
Pour générer un nombre aléatoire, je peux faire :
pour un entier : random(10,20) pour un nombre entre 10 et 19 inclus (je vais voir si ça fonctionne pour des négatifs)
pour un float : esp_random() / UINT32_MAX pour une nombre entre 0 et 1
Donc, deux façons de générer, selon le type. Il faut donc que je sache le type : une façon est de tester la valeur du max if (std::numeric_limits<T>::max() > UINT32_MAX) ...
Il y a plus simple ?
template <typename T>
T nombreAleatoire(T vMin, T vMax) {
return ...
}
et que vous appelez nombreAleatoire<byte>(a, b);
les éléments a et b auront été promus en byte lors de l'appel avec les règles du compilateur donc dans la fonction vous aurez déjà perdu de l'info.
par exemple
template <typename T>
T nombreAleatoire(T vMin, T vMax) {
Serial.print(vMin);
Serial.write(',');
Serial.print(vMax);
Serial.print(F(" -> "));
return (T) random(vMin, vMax);
}
void setup() {
Serial.begin(115200); Serial.println();
}
void loop() {
long a = 256, b = 260, r;
r = nombreAleatoire<uint8_t>(a, b);
Serial.println(r);
delay(1000);
}
même si a et b sont des long, une fois arrivés dans la fonction on aura conservé que l'octet de poids faible et le nombre aléatoire est généré entre 0 et 4 et non pas entre 256 et 260
C'est vrai, je n 'avais pas pensé à ça. Il faut donc s'assurer que els bornes sont cohérentes avant d'appeler la fonction. La fonction doit juste savoir quel type de génération elle doit faire. Je vais investiguer esp_random() et random()
Merci du tuyau...
EDIT: random(a,b) renvoie un nombre entier entre a et b, au format qu'on lui demande (int ou float) esp_random() renvoie un uint32_t. Pour obtenir un float entre 0 et 1, on peut faire
uint32_t y = esp_random();
float z = (float)y/UINT32_MAX;
La fonction random arduino prend des long comme paramètres et esp_random() ne prend pas de paramètre et retourne un uin32_t (donc on connait sa taille)
vous voudriez une fonction random qui retourne un double ou un float?
sinon vous avez besoin de tester le type dans le template (et typeid() n'est pas supporté à cause des flags de compilation) et donc vous perdez l'intérêt du template
de plus le compilateur risque de se mélanger les pinceaux car un int peut être promu en double
Je cible l'ESP32 car le but est de programmer un perceptron multicouche, de manière plus propre que ma précédente version. Un AVR ne supporterait probablement pas le besoin en mémoire.