473,320 Members | 1,936 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Template magic needed, partial specialization

I've been banging my head in the wall for some time now over a
little problem having to do with partial specialization of
function templates.

The real problem is more complex than this, but after trimming
out irrelevant stuff, this is what remains. The problem is to
have a function template with different specialization for
signed an unsigned template parameters. Lets assume for now that
I want to test signed arguments for negative values and do
something special with these cases, while unsigned arguments
should not be tested at all.

Consider the following code:

#include <iostream>
#include <limits>

/*
* Helper function called by f<IntType>.
*/
template <typename IntType, bool is_signed> void g(IntType x);

/* Now I want to have two specializations of the above: */
template <typename IntType>
void g<IntType, true>(IntType x) /* Signed types end up here */
{
if (x < 0) { /* ok, x is signed */
/* Special logic here */
}
}

template <typename IntType>
void g<IntType, false>(IntType)
{
/* x is unsigned, so don't have to do anything */
}

/*
* Function called by main. Only template parameter
* is the IntType.
*/
template <typename IntType>
void
f(IntType x)
{
#if 0
/* This would result in compiler warnings if IntType is unsigned: */
if (numeric_limits<IntType>::is_signed && x < 0) {
/* special logic here */
}
#else
/* So let's try this instead */
g<IntType, numeric_limits<IntType>::is_signed>(x);

#endif
/* More logic here */
}

int
main()
{
unsigned char uc = -1;
unsigned short us = -1;
unsigned int ui = -1;
unsigned long ul = -1L;
signed char sc = -1;
signed short ss = -1;
signed int si = -1;
signed long sl = -1L;

f(uc);
f(us);
f(ui);
f(ul);

f(sc);
f(ss);
f(si);
f(sl);

return 0;
}

The compiler complains with the following message:
foo.cc:11: error: function template partial specialization
'g<IntType, true>' is not allowed

I'd appreciate some hints how to get on.

When this is solved I'll have to deal with right shifting:

typedef unsigned short MyInt;
const MyInt my_int_mask = -1;

template <typename UnsignedIntType>
void f(UnsignedIntType x)
{

while (x > 0) {
MyInt y = x /* & my_int_mask */;
/* do something with y */
/* next line does not work if sizeof y >= sizeof x */
x >>= numeric_limits<MyInt>::digits; /* more template magic needed */
}
}

/Niklas Norrthon
Dec 6 '05 #1
5 2228
* Niklas Norrthon:

I've been banging my head in the wall for some time now over a
little problem having to do with partial specialization of
function templates.
You're aware that there's no such?

The real problem is more complex than this, but after trimming
out irrelevant stuff, this is what remains. The problem is to
have a function template with different specialization for
signed an unsigned template parameters. Lets assume for now that
I want to test signed arguments for negative values and do
something special with these cases, while unsigned arguments
should not be tested at all.
To detect signedness at compile time you can do something like

template< typename T >
struct IsSigned
{
enum{ yes = (T(-1) < 0), no = !yes };
};

int main()
{
std::cout << IsSigned<unsigned>::yes << std::endl;
std::cout << IsSigned<signed>::yes << std::endl;
}

Consider the following code:
[snip] template <typename IntType>
void
f(IntType x)
{
#if 0
/* This would result in compiler warnings if IntType is unsigned: */
if (numeric_limits<IntType>::is_signed && x < 0) {
/* special logic here */
}
#else
/* So let's try this instead */
g<IntType, numeric_limits<IntType>::is_signed>(x);
You can't use the result of a run-time call at compile time.
[snip] I'd appreciate some hints how to get on.


The best is to write code that's signedness-agnostic.

Failing that, you can use the technique shown above.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Dec 6 '05 #2
al***@start.no (Alf P. Steinbach) writes:
* Niklas Norrthon:

I've been banging my head in the wall for some time now over a
little problem having to do with partial specialization of
function templates.
You're aware that there's no such?


Now I am, after digging out the standard and looking for it, and
some googling of the archives. I also became aware of that I'm
not the only one missing partial specialization of function
templates, and I see no reason why it couldn't be included in
the language, so I hope it'll find it way in eventually.
To detect signedness at compile time you can do something like

template< typename T >
struct IsSigned
{
enum{ yes = (T(-1) < 0), no = !yes };
};

int main()
{
std::cout << IsSigned<unsigned>::yes << std::endl;
std::cout << IsSigned<signed>::yes << std::endl;
}
Which leaves me with exactly the same compiler warning I wanted to
get rid of in the first place.

I admit it's no big deal. The compiler warns me that comparing
an unsigned to less than zero will always result in false. The
problem is that it is in a template, so I will get the warning
for every type I instanciate the template with, and each warning
is three or four lines, since it also tells me where the
template is instanciated and so on, and the code lives in a
header file, so I get it for every file including the header,
which in the end leaves me with pages of useless warnings.

It also gave me the opportunity to dig into some pretty advanced
template hacking, which is something I don't do every day, and
I have learned (I think) when and why I need to say
template<> sometimes, and when I need to specify types with
typename.
Consider the following code:

[snip]
template <typename IntType>
void
f(IntType x)
{
#if 0
/* This would result in compiler warnings if IntType is unsigned: */
if (numeric_limits<IntType>::is_signed && x < 0) {
/* special logic here */
}
#else
/* So let's try this instead */
g<IntType, numeric_limits<IntType>::is_signed>(x);


You can't use the result of a run-time call at compile time.


What are you talking about?
IntType is the template argument from above, known at compile time.
numeric_limits<IntType>::is_signed is a static constant bool
defined in the header <limits> for all built in types, and also
known at compile time. The above would expand to one of:

g<unsigned char, false>(x);
g<signed char, true>(x);
g<char, true>(x);
g<char, false>(x);
g<unsigned short, false>(x);
g<signed short, true>(x);
g<unsigned int, false>(x);
g<signed int, true>(x);
g<unsigned long, false>(x);
g<signed long, true>(x);

Or some other user defined type for which numeric_limits is specialized.
[snip]
I'd appreciate some hints how to get on.


The best is to write code that's signedness-agnostic.

Failing that, you can use the technique shown above.


Failing that, the outcommented code works fine. I just wanted to
get rid of loads of warnings, and learning some advanced
template programming. I did the latter but not the former...

/Niklas Norrthon
Dec 7 '05 #3
* Niklas Norrthon:
* Alf P. Steinbach:

To detect signedness at compile time you can do something like

template< typename T >
struct IsSigned
{
enum{ yes = (T(-1) < 0), no = !yes };
};

int main()
{
std::cout << IsSigned<unsigned>::yes << std::endl;
std::cout << IsSigned<signed>::yes << std::endl;
}
Which leaves me with exactly the same compiler warning I wanted to
get rid of in the first place.


If that warning is due to your having no partial specialization,
consider the simple trick of putting your function in a class. Classes
can be partially specialized. Another trick is to use function
overloading: you can't partially specialize a function, but you can
overload it, so in this case transform the boolean value to a type, one
for true and one for false, and use a dummy argument of that type.

/* So let's try this instead */
g<IntType, numeric_limits<IntType>::is_signed>(x);


You can't use the result of a run-time call at compile time.


What are you talking about?


I'm very sorry, bowing head in shame and applying the nearest wall to my
forehead: it was a parse error, on my part, and furthermore there was no
need for my IsSigned class (except it's usually faster to just code such
a thing than read the docs...).
[snip] Failing that, the outcommented code works fine. I just wanted to
get rid of loads of warnings, and learning some advanced
template programming. I did the latter but not the former...


Hope the above helps with both, then,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Dec 7 '05 #4
Niklas Norrthon <do********@invalid.net> writes:
I've been banging my head in the wall for some time now over a
little problem having to do with partial specialization of
function templates.
Finally I found a solution to my problem, that I think is
useful enough to share.

/*
* Instead of partial specialization of the function
* templates, first I introduce a dummy template class
* with two possible specializations:
*/

template <bool is_signed>
struct IsSigned { };

/*
* Then I define two versions of the function where the
* actual logic resides. They are overloaded with the
* dummy class above:
*/

/* signed version: */
template <typename IntType>
void g(IntType x, Signed<true> /* dummy arg */)
{
if (x < 0) {
/* special logic here */
}
}

/* Unsigned version */
template <typename IntType>
void g(IntType x, Signed<false> /* dummy arg */)
{
/* do nothing, or do special unsigned logic here */
}

/*
* Finally I have the one parameter version, which
* is called from outside:
*/

/* Common version */
template <typename IntType>
void g(IntType x)
{
/* First special treatment depending on signedness: */
g(x, Signed<numeric_limits<IntType>::is_signed>());

/* Then common logic to both signed and unsigned types */
}

/* Finally my main unchanged from before: */
int
main()
{
unsigned char uc = -1;
unsigned short us = -1;
unsigned int ui = -1;
unsigned long ul = -1L;
signed char sc = -1;
signed short ss = -1;
signed int si = -1;
signed long sl = -1L;

f(uc);
f(us);
f(ui);
f(ul);

f(sc);
f(ss);
f(si);
f(sl);

return 0;
}


/Niklas Norrthon
Dec 7 '05 #5
al***@start.no (Alf P. Steinbach) writes:
If that warning is due to your having no partial specialization,
consider the simple trick of putting your function in a class. Classes
can be partially specialized. Another trick is to use function
overloading: you can't partially specialize a function, but you can
overload it, so in this case transform the boolean value to a type, one
for true and one for false, and use a dummy argument of that type.
This is exactly what I ended up with, see my other post. Partial
specializations of function templates would have been a little bit
more elegant IMHO, but overloading with a dummy argument works, so
for the time being that is what I'll do.

Still hope for partial specializations in the future though, and I
see no reason not to include them in the language sooner or later.
Hope the above helps with both, then,


Thanks for your comments, problem finally solved. (Also the
right_shift part which a mentioned in my original post, which
was trivial in the end).

/Niklas Norrthon
Dec 7 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
by: Paul MG | last post by:
Hi Template partial specialization always seems like a fairly straightforward concept - until I try to do it :). I am trying to implement the input sequence type (from Stroustrup section...
8
by: Agent Mulder | last post by:
Hi group, I have a problem with partial template specialization. In the code below I have a template struct Music with one method, play(), and three kinds of music, Jazz, Funk and Bach. When I...
4
by: TT \(Tom Tempelaere\) | last post by:
Comeau compiler complains (too few arguments for class template "B") at line *** #include <memory> template<typename T, size_t n> struct A {}; template<typename T, size_t n> struct B;
5
by: Levent | last post by:
Hi, Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1): #include <iostream> template<class T, unsigned N> struct Foo { void func(); }; template<class T, unsigned N>
4
by: Alfonso Morra | last post by:
Does VC 7.1 support template specialization and partial specialization ?
9
by: Marek Vondrak | last post by:
Hello. I have written the following program and am curious why it prints "1" "2". What are the exact effects of explicitly providing function template parameters at the call? Is the second...
9
by: stephen.diverdi | last post by:
Can anyone lend a hand on getting this particular template specialization working? I've been trying to compile with g++ 4.1 and VS 2005. ...
8
by: flopbucket | last post by:
Hi, I want to provide a specialization of a class for any type T that is a std::map. template<typename T> class Foo { // ... };
1
by: Ioannis Gyftos | last post by:
Hello, First the code :) /////////////////////////////////////////////////////////////////////////////////// // in another header file namespace LJC{
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.