I have a template function with a single parameter <T>
, and I would like to make specializations of this function for different integral types. This seemed obvious at first, however after few attempts I found that I do not really understand how the specialization really works here, and how to achieve some degree of portability...
Here's the test program:
// clang test.cc -std=c++11 -lc++
#include <iostream>
#include <typeinfo>
template <typename T> void foo() { std::cout << " foo<T> with T=" << typeid(T).name() << '\n'; }
template <> void foo<int>() { std::cout << " foo<int>\n"; }
template <> void foo<long>() { std::cout << " foo<long>\n"; }
template <> void foo<long long>() { std::cout << " foo<long long>\n"; }
template <> void foo<size_t>() { std::cout << " foo<size_t>\n"; }
// template <> void foo<int64_t>() { std::cout << " foo<int64_t>\n"; } // error
int main () {
std::cout << "sizeof(int)=" << sizeof(int) << ", ";
std::cout << "sizeof(long)=" << sizeof(long) << ", ";
std::cout << "sizeof(long long)=" << sizeof(long long) << ", ";
std::cout << "sizeof(size_t)=" << sizeof(size_t) << "\n";
foo<int>();
foo<long>();
foo<long long>();
foo<size_t>();
foo<ssize_t>();
foo<int8_t>();
foo<int16_t>();
foo<int32_t>();
foo<int64_t>();
foo<uint32_t>();
foo<uint64_t>();
return 0;
}
and on my machine it produces
sizeof(int)=4, sizeof(long)=8, sizeof(long long)=8, sizeof(size_t)=8
foo<int>
foo<long>
foo<long long>
foo<size_t>
foo<long>
foo<T> with T=a
foo<T> with T=s
foo<int>
foo<long long>
foo<T> with T=j
foo<T> with T=y
So here's what I don't understand:
- If
long
andlong long
is the same type, why does the compiler allow both specializations to coexist? - Why adding a specialization for
int64_t
produces an error? - Why
foo<int64_t>
resolves asfoo<long long>
and notfoo<long>
? - Why
foo<ssize_t>
resolves asfoo<long>
and notfoo<long long>
? - Why
foo<uint64_t>
does not use specializationfoo<size_t>
? - Is the behavior that I observe here universal, or machine-specific? How can I be sure that this code is portable?