By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,304 Members | 2,037 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,304 IT Pros & Developers. It's quick & easy.

Template specialization problems

P: n/a
I have a small program like this:

////////////////////////////////////////////////
#include <iostream>
using namespace std ;

// set bits in an address
template <typename T>
inline T*
set_addr(const T* addr, unsigned long n) {
return (T*)( (unsigned long)addr | n) ;
}

// helper class that clears the last two bits of an address
template <typename T, int S>
struct clear_addr_helper {} ;

// 32 bit pointer specialization
template <typename T>
struct clear_addr_helper<T,4> {
static inline T*
clear(const T* addr) {
return (T*)( (unsigned long)addr & 0xfffffffc) ;
}
} ;

// 64 bit pointer specialization
template <typename T>
struct clear_addr_helper<T,8> {
static inline T*
clear(const T* addr) {
return (T*)( (unsigned long)addr & 0xfffffffffffffffc) ;
}
// a function that won't compile
static inline void
error() { ss }
} ;

template <typename T>
inline T*
clear_addr(const T* addr) {
return clear_addr_helper<T,sizeof(T*)>::clear(addr) ;
}

int
main() {
short* p = new short(1) ;

cout << "sizeof(short*): " << sizeof(short*) << endl ;
cout << "p = " << p << endl ;
cout << "set_addr(p,0x1): " << set_addr(p,0x1) << endl ;
cout << "clear_addr(set_addr(p,0x2)): "
<< clear_addr(set_addr(p,0x2)) << endl ;
}
////////////////////////////////////////////////

g++ (version 4.0.1) won't compile this program on a 32 bit machine. It
complained the 64 bit specialization: the "0xfffffffffffffffc" in the
"clear" method is too large, and the "error" method is in error. But
since on a 32 bit machine, only the 32 bit pointer template
specialization is needed. It seems that g++ has looked both of them.
Other compilers such as the Intel/Sun Workshop/SGI C++ compilers all
compiled the above code without problem. I think they all didn't look at
the 64 bit pointer template specialization.

Is this behavior implementation dependent? Is there a way (a
command-line option) to make g++ behave like others?? Or I cannot assume
a lazy instantiation for the compiler?

Thanks in advance,
--Yang
Apr 1 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a

"Yang Zhang" <sp**@no.spam.com> skrev i meddelandet
news:W4****************@bignews5.bellsouth.net...
I have a small program like this:

////////////////////////////////////////////////
#include <iostream>
using namespace std ;

// set bits in an address
template <typename T>
inline T*
set_addr(const T* addr, unsigned long n) {
return (T*)( (unsigned long)addr | n) ;
}

// helper class that clears the last two bits of an address
template <typename T, int S>
struct clear_addr_helper {} ;

// 32 bit pointer specialization
template <typename T>
struct clear_addr_helper<T,4> {
static inline T*
clear(const T* addr) {
return (T*)( (unsigned long)addr & 0xfffffffc) ;
}
} ;

// 64 bit pointer specialization
template <typename T>
struct clear_addr_helper<T,8> {
static inline T*
clear(const T* addr) {
return (T*)( (unsigned long)addr & 0xfffffffffffffffc) ;
}
// a function that won't compile
static inline void
error() { ss }
} ;

template <typename T>
inline T*
clear_addr(const T* addr) {
return clear_addr_helper<T,sizeof(T*)>::clear(addr) ;
}

int
main() {
short* p = new short(1) ;

cout << "sizeof(short*): " << sizeof(short*) << endl ;
cout << "p = " << p << endl ;
cout << "set_addr(p,0x1): " << set_addr(p,0x1) << endl ;
cout << "clear_addr(set_addr(p,0x2)): "
<< clear_addr(set_addr(p,0x2)) << endl ;
}
////////////////////////////////////////////////

g++ (version 4.0.1) won't compile this program on a 32 bit machine.
It complained the 64 bit specialization: the "0xfffffffffffffffc" in
the "clear" method is too large, and the "error" method is in error.
But since on a 32 bit machine, only the 32 bit pointer template
specialization is needed. It seems that g++ has looked both of them.
Other compilers such as the Intel/Sun Workshop/SGI C++ compilers all
compiled the above code without problem. I think they all didn't
look at the 64 bit pointer template specialization.
Whether it is used/needed or not, all code must be valid. You cannot
have an integer constant outside the range of integers.

Is this behavior implementation dependent? Is there a way (a
command-line option) to make g++ behave like others?? Or I cannot
assume a lazy instantiation for the compiler?


You can only assume that valid code should compile.
You *can* form the unsigned long constant by using the complement
operator, like ~3UL. You cannot, however, assume that a pointer is of
the same size as an unsigned long, or that an unsigned long has 32 or
64 bits. That is also implementation dependent.
Bo Persson
Apr 1 '06 #2

P: n/a
Yang Zhang wrote:
I have a small program like this:

////////////////////////////////////////////////
#include <iostream>
using namespace std ;

// set bits in an address
template <typename T>
inline T*
set_addr(const T* addr, unsigned long n) {
return (T*)( (unsigned long)addr | n) ;
}

// helper class that clears the last two bits of an address
template <typename T, int S>
struct clear_addr_helper {} ;

// 32 bit pointer specialization
template <typename T>
struct clear_addr_helper<T,4> {
static inline T*
clear(const T* addr) {
return (T*)( (unsigned long)addr & 0xfffffffc) ;
}
} ;

#ifdef USE_64_BIT // or whatever macro you have for the same effect
// 64 bit pointer specialization
template <typename T>
struct clear_addr_helper<T,8> {
static inline T*
clear(const T* addr) {
return (T*)( (unsigned long)addr & 0xfffffffffffffffc) ;
}
// a function that won't compile
static inline void
error() { ss }
} ;
#endif

template <typename T>
inline T*
clear_addr(const T* addr) {
return clear_addr_helper<T,sizeof(T*)>::clear(addr) ;
}

int
main() {
short* p = new short(1) ;

cout << "sizeof(short*): " << sizeof(short*) << endl ;
cout << "p = " << p << endl ;
cout << "set_addr(p,0x1): " << set_addr(p,0x1) << endl ;
cout << "clear_addr(set_addr(p,0x2)): "
<< clear_addr(set_addr(p,0x2)) << endl ;
}
////////////////////////////////////////////////

g++ (version 4.0.1) won't compile this program on a 32 bit machine. It
complained the 64 bit specialization: the "0xfffffffffffffffc" in the
"clear" method is too large, and the "error" method is in error. But
since on a 32 bit machine, only the 32 bit pointer template
specialization is needed. It seems that g++ has looked both of them.
Other compilers such as the Intel/Sun Workshop/SGI C++ compilers all
compiled the above code without problem. I think they all didn't look at
the 64 bit pointer template specialization.
Well, I think the error was reported early in the lexical analysis where
your 64bit address gets transformed into a token stored for later use.
So even if you don't instantiate the specialization you still get an error

Is this behavior implementation dependent? Is there a way (a
command-line option) to make g++ behave like others?? Or I cannot assume
a lazy instantiation for the compiler?
Notice the use of a preprocessor macro above. This is what i think the
most effective way.

Thanks in advance,
--Yang


regards,
Ben
Apr 2 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.