6

Consider this function template:

template<typename T>
unsigned long f(void *) { return 0;}

Now, I print the addresses of f<A> and f<B> as:

std::cout << (void*)f<A> << std::endl;
std::cout << (void*)f<B> << std::endl;

Why do they print the same address if compiled in MSVS10? Are they not two different functions and therefore should print different addresses?

Updated:

I realized that on ideone, it prints the different address. MSVS10 optimizes the code, as the function doesn't depend on T in any way, so it produces same function. @Mark's answer and comments on this are valuable. :-)

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • @NicolBolas: Go through the link. Click on [`same address`](http://ideone.com/MPXnt) in the question. – Nawaz Feb 17 '12 at 05:22
  • 2
    Does the standard say that functions have to have unique addresses? I would think that they would leave that as completely undefined (implementation defined) to allow the possibility of compiler optimization. – Martin York Feb 17 '12 at 05:23
  • Well of course if you change the function body to depend on the template type, the functions won't be the same anymore. – Mark Ransom Feb 17 '12 at 05:27
  • @MarkRansom: But according to you, it is still the same function, as it prints `1`. @bdonlan's answer seem to be correct. – Nawaz Feb 17 '12 at 05:38
  • 1
    I suggest that even if you follow bdorian's suggestion you will still get the same address unless the signature or body of the function depends in some way on the template parameter. Your original function body did not depend on the template parameter but your second version does. – Mark Ransom Feb 17 '12 at 05:43

3 Answers3

7

You need to cast to void *:

std::cout << (void*)(ftype*)f<A> << std::endl;
std::cout << (void*)(ftype*)f<B> << std::endl;

If you cast to a function pointer (or several other classes of non-void pointers), it will be interpreted as a bool by the operator<< for std::ostream (hence the 1).

bdonlan
  • 224,562
  • 31
  • 268
  • 324
2

Since the function doesn't depend on the template parameter, the compiler can condense all instantiations into a single function.

I don't know why you get 1 for the address.


Added by Nawaz:

I experimented with my real code, and concluded that what @Mark said above is very important here :

Since the function doesn't depend on the template parameter, the compiler can condense all instantiations into a single function.

I also came to a conclusion that if the function-body depends on T*, not on T, it still produces the same function for different type arguments in my real code (not on ideone, though). However, if it depends on T, then it produces different functions, because sizeof(T) differs (fortunately for me) for different type arguments.

So I added a dummy automatic variable of type T in the function template, so that the function could depend on the size of T so as to force it to produce different functions.

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I experimented with my real code, and concluded that this information is imporant : *Since the function doesn't depend on the template parameter, the compiler can condense all instantiations into a single function.* I also came to a conclusion that if the function-body depends on `T*`, not on `T`, it still produces the same function. However, if it depends on `T`, then it produces different functions, since the `sizeof(T)` differs (fortunately) for different type argument. – Nawaz Feb 17 '12 at 05:58
1

This is simply a case of undefined behavior because the results of casting a pointer to a function to a pointer to object type are undefined.

A more interesting expression to examine would bef<A> == f<B> which should evaluate to true if and only if A and B refer to the same type.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656