1

The code below generates a warning with -Wsign-conversion. It generates the warning at the line T digit = a % base.

I want to extract the signed-ness of T and then cast base to that signed-ness to squash the warning.

I'm trying to avoid specializations because that just duplicates code (the only thing that's going to change is the signed-ness of base). I'm also trying to avoid casting base to a T in case its a non-POD type like a Integer (which is optimized for the reduction with longs).

How do I extract the signed-ness of T?


Related, the code base is effectively C++98 and C++03, so it does not have some features (like discussed in Partial template specialization based on “signed-ness” of integer type?).


template <class T>
std::string IntToString(T a, unsigned int base = 10)
{
    if (a == 0)
        return "0";
    bool negate = false;
    if (a < 0)
    {
        negate = true;
        a = 0-a;    // VC .NET does not like -a
    }
    std::string result;
    while (a > 0)
    {
        T digit = a % base;
        result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
        a /= base;
    }
    if (negate)
        result = "-" + result;
    return result;
}
Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • In your case, it is `a` which should be converted to `unsigned`. (and it would fix edge case (`IntToString(-128)`). – Jarod42 Jul 06 '15 at 09:00
  • The C++11 type traits library comes from boost. I strongly suggest to use the Boost.TypeTraits library in C++98/03, rather than roll out your own metafunctions. – sbabbi Jul 06 '15 at 09:52
  • @sbabbi - The library uses C++03, and does not have external dependencies. Also, Boost cannot pass acceptance testing. Finally, Boost does not work with the certain Windows-based configurations. – jww Jul 06 '15 at 10:34

3 Answers3

2

Pre-C++11 you can use this implementation of std::conditional:

template<bool B, class T, class F>
struct conditional { typedef T type; };
template<class T, class F>
struct conditional<false, T, F> { typedef F type; };

Then we can write a struct to extract the signedness of a type:

template <typename T>
struct signedness {
    typedef typename conditional<T(-1)<T(0),int,unsigned>::type type;   
};

Then just declare base as being that type:

std::string IntToString(T a, 
    typename signedness<T>::type base = 10){
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • Thank you very much. It worked like a charm on modern GCC and Clang. Next is a round of testing with OpenBSD and Visual Studio (cross-platform libraries can be a pain at times). – jww Jul 06 '15 at 09:50
0

You can check whether a type is signed using the is_signed funtcion, and whether it is unsigned using the is_unsigned function.

To convert a type to the corresponding signed version use make_signed and to the corresponding unsigned vesrion use make_unsigned.

Sorry, did not read the C++98 part until now.

Tommy Andersen
  • 7,165
  • 1
  • 31
  • 50
0

The signedness of T can be deduced as std::is_signed<T>::value as from http://en.cppreference.com/w/cpp/types/is_signed

Give a look also to the entire type support library for eventual other similar functions about static properties of types.

The type for base shuld be

std::conditional<std::is_signed<T>::value, int, unsigned>::type
Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63