Déroulé de boucle via un template
Bonjour à tous !
J'utilise depuis longtemps dans un de mes programme des fonctions permettant de lire le contenu d'un std::array de uint8_t. J'ai 3 fonctions génériques permettant de retourner soit un uint8_t, soit un uint16_t, soit un uint32_t.
Code:
1 2 3 4 5 6
|
template<typename U, ::std::size_t N>
uint8_t RawRead8(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
{
return arr[adr];
} |
Code:
1 2 3 4 5 6
|
template<typename U, ::std::size_t N>
uint16_t RawRead16(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
{
return arr[adr + 0] << 8 | arr[adr + 1];
} |
Code:
1 2 3 4 5 6
|
template<typename U, ::std::size_t N>
uint32_t RawRead32(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
{
return arr[adr + 0] << 24 | arr[adr + 1] << 16 | arr[adr + 2] << 8 | arr[adr + 3];
} |
Rien de bien folichon donc, mais ça oblige à créer autant de fonctions que de type de retour ...
J'ai donc voulu créer une unique fonction permettant de gérer autant de types que voulu (par ex retourner aussi un uint64_t).
Voici le résultat :
Code:
1 2 3 4 5 6 7 8 9 10 11
| template<typename T, typename U, ::std::size_t N>
decltype(auto) RawRead(const ::std::array<U, N> & arr, const ::std::uint32_t& adr)
{
T returnValue{};
for (uint8_t i = 0; i <= sizeof(T) - 1; ++i) {
returnValue <<= 8;
returnValue |= arr[adr + i];
}
return returnValue;
} |
Et un exemple d'utilisation:
Code:
1 2 3 4 5 6 7 8
|
std::array <uint8_t, 0x100> memory;
memory[0] = 0xFE;
memory[1] = 0xDC;
memory[2] = 0xBA;
memory[3] = 0x98;
auto val32 = RawRead<uint32_t>(memory, 0x0); |
Ce code fonctionne parfaitement. Mais lors de la vérification du code assembleur généré, je me rends compte que cette dernière fonction génère le code correspondant à la boucle, au lieu de faire une série de décalage à gauche comme la première fonction :(
Existe-t-il un moyen pour forcer le compilateur à dérouler la boucle ? Je ne suis pas assez calé en templates pour avoir la solution (je ne suis même pas sûr que ce soit faisable).
Merci de m'avoir lu :)