Upsigning or downsigning

D

Damian

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
 
F

Fei Liu

Damian said:
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
 
A

Abhishek Padmanabh

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);}
 
T

tragomaskhalos

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.
 
D

Damian

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




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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top