#include <iostream>
namespace foo_detail {
template <typename T>
struct remap {
// Default: Output type is the same as input type.
typedef T type;
};
template <>
struct remap<char> {
typedef unsigned char type;
};
template <>
struct remap<signed char> {
typedef unsigned char type;
};
template <typename T>
void foo(int x);
template <>
void foo<unsigned char>(int x) {
std::cout << "foo<unsigned char>(" << x << ") called\n";
}
}
template <typename T>
void foo(int x) {
foo_detail::foo<typename foo_detail::remap<T>::type>(x);
}
int main() {
foo<char>(13);
foo<signed char>(13);
foo<unsigned char>(13);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKbmFtZXNwYWNlIGZvb19kZXRhaWwgewp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IHJlbWFwIHsKICAgIC8vIERlZmF1bHQ6IE91dHB1dCB0eXBlIGlzIHRoZSBzYW1lIGFzIGlucHV0IHR5cGUuCiAgICB0eXBlZGVmIFQgdHlwZTsKfTsKCnRlbXBsYXRlIDw+CnN0cnVjdCByZW1hcDxjaGFyPiB7CiAgICB0eXBlZGVmIHVuc2lnbmVkIGNoYXIgdHlwZTsKfTsKCnRlbXBsYXRlIDw+CnN0cnVjdCByZW1hcDxzaWduZWQgY2hhcj4gewogICAgdHlwZWRlZiB1bnNpZ25lZCBjaGFyIHR5cGU7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kdm9pZCBmb28oaW50IHgpOwoKdGVtcGxhdGUgPD4Kdm9pZCBmb288dW5zaWduZWQgY2hhcj4oaW50IHgpIHsKICAgIHN0ZDo6Y291dCA8PCAiZm9vPHVuc2lnbmVkIGNoYXI+KCIgPDwgeCA8PCAiKSBjYWxsZWRcbiI7Cn0KfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnZvaWQgZm9vKGludCB4KSB7CiAgICBmb29fZGV0YWlsOjpmb288dHlwZW5hbWUgZm9vX2RldGFpbDo6cmVtYXA8VD46OnR5cGU+KHgpOwp9CgppbnQgbWFpbigpIHsKICAgIGZvbzxjaGFyPigxMyk7CiAgICBmb288c2lnbmVkIGNoYXI+KDEzKTsKICAgIGZvbzx1bnNpZ25lZCBjaGFyPigxMyk7Cn0=