6 votes

Limite C++ d'un int non signé par le biais d'un modèle

J'utilise un modèle pour convertir les types intégraux en une représentation sous forme de chaîne de leurs valeurs binaires. J'ai utilisé ce qui suit :

template<typename T>
std::string ToBinary(const T& value)
{
    const std::bitset<std::numeric_limits<T>::digits + 1> bs(value);
    const std::string s(bs.to_string());

    return s;
}

Il fonctionne pour les int mais ne compile pas avec les unsigned int :

unsigned int buffer_u[10];
int buffer_i[10];
...
ToBinary(buffer_i[1]); //compile and works
ToBinary(buffer_u[1]); //doesn't compile -- ambiguous overload

Pouvez-vous expliquer pourquoi ?

EDITAR:

Oui, j'utilise VS2010

4voto

KasF Points 202

Ce n'est pas votre appel à ToBinary qui est ambigu, c'est l'appel au constructeur de bitset avec une valeur non signée. Malheureusement, il s'agit d'un bogue de VC++ : http://connect.microsoft.com/VisualStudio/feedback/details/532897/problems-constructing-a-bitset-from-an-unsigned-long-in-the-vc-rc

Editer - Solution de contournement :

template<>
std::string ToBinary<unsigned int>(const unsigned int& value)
{
    const std::bitset<std::numeric_limits<unsigned int>::digits> bs(static_cast<unsigned long long>(value));
    return bs.to_string();
}

0voto

Coder02 Points 240

Utilisez-vous VC10 ? Un problème a déjà été signalé : Microsoft connect. Je pense aussi que vous pouvez résoudre le problème en transformant le type en int s'il s'agit d'un 32 bit, comme ceci :

string s = ToBinary(*reinterpret_cast<int*>(&buffer_u[1]));

Cette opération peut également être effectuée à l'intérieur de la méthode si nécessaire. Le résultat de la réinterprétation ne doit cependant plus être utilisé pour l'arithmétique ;)

Pour moi, cette solution de contournement fonctionne très bien (mais elle est assez moche).

template<typename T>
std::string ToBinary(const T& value)
{
    switch (sizeof(T))
    {
    case 8:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const long*>(&value)).to_string();
    case 4:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const int*>(&value)).to_string();
    case 2:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const short*>(&value)).to_string();
    case 1:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const char*>(&value)).to_string();
    }
    return "n/a";
}

0voto

Tony The Lion Points 28208

Si vous regardez la norme (FDIS n3290), vous voyez que std::bitset a plusieurs constructeurs :

Il y a d'abord celle-ci :

20.5.1 Constructeurs d'ensembles de bits [bitset.cons]

constexpr bitset(unsigned long long val) noexcept;

Effets : Construit un objet de la classe bitset, en initialisant les les M premières positions de bits aux valeurs de bits correspondantes dans val. M est le plus petit plus petit de N et du nombre de bits dans la représentation de la valeur (3.9) de unsigned long long. Si M < N, les positions de bits restantes sont initialisées à zéro.

Il y a aussi celle-ci, que je soupçonne d'être une source d'ambigüité, lorsque vous l'appelez avec unsigned int

template <class charT>
explicit bitset(
const charT* str,
typename basic_string<charT>::size_type n = basic_string<charT>::npos,
charT zero = charT(’0’), charT one = charT(’1’));

Effets : Construit un objet de la classe bitset comme si par

bitset( n == basic_string<charT>::npos ? basic_string<charT>(str) :
basic_string<charT>(str, n), 0, n, zero, one)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X