C++: charとsigned charとunsigned charは違う
- C++
( 更新)
#include <iostream>
template<typename T>
void f(T) {
std::cout << "T" << std::endl;
}
void f(signed int) {
std::cout << "signed int" << std::endl;
}
int main() {
f(0); // Tとsigned intのどっちが出力される?
}
この場合は当然signed int
が出力される。
#include <iostream>
template<typename T>
void f(T) {
std::cout << "T" << std::endl;
}
void f(signed char) {
std::cout << "signed char" << std::endl;
}
int main() {
f('A'); // Tとsigned charのどっちが出力される?
}
でもこうするとT
が出力される。罠。
解説
- Cにおいて
char
の符号は処理系定義- この仕様を受け継いだC++は以下の定義
signed char
!=char
unsigned char
!=char
- この仕様を受け継いだC++は以下の定義
- 一方intは符号付きであるという定義
- この仕様を受け継いだC++は以下の定義
signed int
==int
unsigned int
!=int
- この仕様を受け継いだC++は以下の定義
int8_t
とかuint8_t
への特殊化するとたまにやらかす。ちゃんとchar
の特殊化もしようね。
ちなみにsigned charとunsiged charのオーバーロードがある時charを入れるとコンパイルが通らない(オーバーロードが曖昧っていうエラー)
void f(signed char) {}
void f(unsigned char) {}
int main() {
f('A'); // コンパイルエラー
}
char用のオーバーロードを定義してあげるとコンパイルが通る。
void f(char) {}
void f(signed char) {}
void f(unsigned char) {}
int main() {
f('A'); // OK
}
これに黒魔術(SFINAE)が絡んでくるといよいよ訳がわからなくなってくる...