| re: Template specialization problems
"Yang Zhang" <spam@no.spam.com> skrev i meddelandet
news:W4mXf.3200$L6.2726@bignews5.bellsouth.net...[color=blue]
>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.[/color]
Whether it is used/needed or not, all code must be valid. You cannot
have an integer constant outside the range of integers.
[color=blue]
>
> 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?[/color]
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 |