|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Apr 7, 9:40pm, Damian <damian.e...@gmail.com> 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);} |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On 7 Apr, 17:40, Damian <damian.e...@gmail.com> 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. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
On Apr 7, 10:30 am, Abhishek Padmanabh <abhishek.padman...@gmail.com>
wrote: > On Apr 7, 9:40 pm, Damian <damian.e...@gmail.com> 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. |
|
![]() |
| Outils de la discussion | |
|
|