Upsigning or downsigning

Discussion in 'C++' started by Damian, Apr 7, 2008.

  1. Damian

    Damian Guest

    Is there any way to manipulate a template parameter to change its
    signedness?

    For example,

    template <typename T>
    void foo(signed T a, unsigned T b) {

    }

    defines a templated function that is instantiated with a base numeric
    type (e.g. int or long) but is referred by signed and unsigned
    variants.

    Also, how do I convert a typename to signed or unsigned? For example,
    if I had some variable k I wanted to cast to the unsigned variant of
    type T, I'd like to be able to do

    j = (unsigned_type(T))k

    but I'm not sure if it's possible to do something like that. Is there
    anyway to "upsign" (i.e. convert a numeric type to signed) or
    "downsign" (i.e. convert a numeric type to unsigned) similar to how
    one might upcast or downcast a number?

    Thanks!

    Damian Eads
     
    Damian, Apr 7, 2008
    #1
    1. Advertising

  2. Damian

    Fei Liu Guest

    Damian wrote:
    > Is there any way to manipulate a template parameter to change its
    > signedness?
    >
    > For example,
    >
    > template <typename T>
    > void foo(signed T a, unsigned T b) {
    >
    > }
    >
    > defines a templated function that is instantiated with a base numeric
    > type (e.g. int or long) but is referred by signed and unsigned
    > variants.
    >
    > Also, how do I convert a typename to signed or unsigned? For example,
    > if I had some variable k I wanted to cast to the unsigned variant of
    > type T, I'd like to be able to do
    >
    > j = (unsigned_type(T))k
    >
    > but I'm not sure if it's possible to do something like that. Is there
    > anyway to "upsign" (i.e. convert a numeric type to signed) or
    > "downsign" (i.e. convert a numeric type to unsigned) similar to how
    > one might upcast or downcast a number?
    >
    > Thanks!
    >
    > Damian Eads


    Yes, because signed-ness is part of a function signature that function
    overloading uses. You can devise a 'type-of' class template to determine
    if a type is signed or unsigned at compile time.

    Fei
     
    Fei Liu, Apr 7, 2008
    #2
    1. Advertising

  3. On Apr 7, 9:40 pm, Damian <> wrote:
    > Is there any way to manipulate a template parameter to change its
    > signedness?
    >
    > For example,
    >
    >   template <typename T>
    >   void foo(signed T a, unsigned T b) {
    >
    >   }
    >
    > defines a templated function that is instantiated with a base numeric
    > type (e.g. int or long) but is referred by signed and unsigned
    > variants.


    Would have, probably, worked if T worked like a macro replacement but
    it does not.

    >
    > Also, how do I convert a typename to signed or unsigned? For example,
    > if I had some variable k I wanted to cast to the unsigned variant of
    > type T, I'd like to be able to do
    >
    >    j = (unsigned_type(T))k
    >
    > but I'm not sure if it's possible to do something like that. Is there
    > anyway to "upsign" (i.e. convert a numeric type to signed) or
    > "downsign" (i.e. convert a numeric type to unsigned) similar to how
    > one might upcast or downcast a number?


    No that I know of, but there may be. I think what you are trying to do
    is to force the template to work with unsigned types only. There could
    be two ways in which you can accomplish that depending on what you are
    actually trying to do.

    1) Don't let the template instantiate if the type is a signed type
    with something like this, if you want callers to not pass signed
    types:

    template<typename T>
    void func(T t)
    {
    BOOST_STATIC_ASSERT(boost::is_signed<T>::value);
    //rest of the code, T will be signed assuming T is a integral type
    //might put an assert if not boost::is_integral or as required
    }

    2) Provide overloads for the signed types that redirect the call to
    the template with static_cast or explicitly specifying instantiation
    type to make the argument unsigned:

    template<typename T>
    void func(T t)
    {
    //rest code
    }

    void func(int i) { func<unsigned int>(i);}
    void func(char c) { func<unsigned char>(c);}
     
    Abhishek Padmanabh, Apr 7, 2008
    #3
  4. On 7 Apr, 17:40, Damian <> wrote:
    > Also, how do I convert a typename to signed or unsigned? For example,
    > if I had some variable k I wanted to cast to the unsigned variant of
    > type T, I'd like to be able to do
    >
    >    j = (unsigned_type(T))k
    >
    > but I'm not sure if it's possible to do something like that. Is there
    > anyway to "upsign" (i.e. convert a numeric type to signed) or
    > "downsign" (i.e. convert a numeric type to unsigned) similar to how
    > one might upcast or downcast a number?
    >


    How about this ?
    <code>
    template<typename T> struct sign_variants {};
    #define MAKE_SVS_FOR(T) \
    template<> struct sign_variants<T> {\
    typedef T signed_t;\
    typedef unsigned T unsigned_t;\
    };\
    template<> struct sign_variants<unsigned T> {\
    typedef T signed_t;\
    typedef unsigned T unsigned_t;\
    };
    MAKE_SVS_FOR(char)
    // hmmm ... glossing over char vs signed char vs unsigned char ...
    MAKE_SVS_FOR(int)
    MAKE_SVS_FOR(long)
    MAKE_SVS_FOR(short)
    // add any other flavours your compiler supports

    #undef MAKE_SVS_FOR

    // then e.g.
    #include <iostream>

    const char* foo(long x)
    { return "slong"; }
    const char* foo(unsigned long x)
    { return "ulong"; }

    void signedness()
    {
    std::cout << foo(sign_variants<long>::signed_t()) << '\n';
    std::cout << foo(sign_variants<long>::unsigned_t()) << '\n';
    std::cout << foo(sign_variants<unsigned long>::signed_t()) << '\n';
    std::cout << foo(sign_variants<unsigned long>::unsigned_t()) <<
    '\n';
    }
    /*
    output
    slong
    ulong
    slong
    ulong
    */
    </code>

    Obviously you'd use sign_variants inside a template.
     
    tragomaskhalos, Apr 7, 2008
    #4
  5. Damian

    Damian Guest

    On Apr 7, 10:30 am, Abhishek Padmanabh <>
    wrote:
    > On Apr 7, 9:40 pm, Damian <> wrote:
    >
    > > Is there any way to manipulate a template parameter to change its
    > > signedness?

    >
    > > For example,

    >
    > > template <typename T>
    > > void foo(signed T a, unsigned T b) {

    >
    > > }

    >
    > > defines a templated function that is instantiated with a base numeric
    > > type (e.g. int or long) but is referred by signed and unsigned
    > > variants.

    >
    > Would have, probably, worked if T worked like a macro replacement but
    > it does not.
    >
    > > Also, how do I convert a typename to signed or unsigned? For example,
    > > if I had some variable k I wanted to cast to the unsigned variant of
    > > type T, I'd like to be able to do

    >
    > > j = (unsigned_type(T))k

    >
    > > but I'm not sure if it's possible to do something like that. Is there
    > > anyway to "upsign" (i.e. convert a numeric type to signed) or
    > > "downsign" (i.e. convert a numeric type to unsigned) similar to how
    > > one might upcast or downcast a number?

    >
    > No that I know of, but there may be. I think what you are trying to do
    > is to force the template to work with unsigned types only. There could
    > be two ways in which you can accomplish that depending on what you are
    > actually trying to do.
    >
    > 1) Don't let the template instantiate if the type is a signed type
    > with something like this, if you want callers to not pass signed
    > types:
    >
    > template<typename T>
    > void func(T t)
    > {
    > BOOST_STATIC_ASSERT(boost::is_signed<T>::value);
    > //rest of the code, T will be signed assuming T is a integral type
    > //might put an assert if not boost::is_integral or as required
    >
    > }


    Ah, so passing an unsigned type here generates an assertion. I see
    that you address how to handle overloading with signed types below.

    > 2) Provide overloads for the signed types that redirect the call to
    > the template with static_cast or explicitly specifying instantiation
    > type to make the argument unsigned:
    >
    > template<typename T>
    > void func(T t)
    > {
    > //rest code
    >
    > }
    >
    > void func(int i) { func<unsigned int>(i);}
    > void func(char c) { func<unsigned char>(c);}


    Since I was asked by several people already for an example. I will
    give one. Suppose you want to take the absolute value on a value of
    any integer type. The absolute value of an unsigned would just leave
    the value unchanged and the absolute value of a signed type would set
    the signed bit to naught.
     
    Damian, Apr 7, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page