この記事は、初心者C++er Advent Calendar 2016の23日目の記事です。
WindowsのVisual C++でこんなコードを書き始めたんです。
#include <cstdint> #include <windows.h> void f(std::uint8_t) {} void f(std::uint16_t) {} void f(std::uint32_t) {} void f(std::uint64_t) {} |
符号無し整数型をすべて網羅するよう、関数fを多重定義したわけです。さらにコードを書き進めます。
int main() { DWORD x = 12345; f(x); } |
こんなコードを書いたら、コンパイルエラーになってしまいました。
t.cpp
t.cpp(12): error C2668: ‘f’: オーバーロード関数の呼び出しを解決することができません。(新機能 ; ヘルプを参照)
t.cpp(7): note: ‘void f(uint64_t)’ の可能性があります
t.cpp(6): note: または ‘void f(uint32_t)’
t.cpp(5): note: または ‘void f(uint16_t)’
t.cpp(4): note: または ‘void f(uint8_t)’
t.cpp(12): note: 引数リスト ‘(DWORD)’ を一致させようとしているとき
cstdintの中のstdint.hとwindows.hを見て原因を突き止めました。
- uint32_tはunsigned intからのtypedef。
- 一方、DWORDはunsigned longからのtypedef。
どうやら、コンパイラはunsigned longをunsigned intにするかunsigned long longにするか、決められなかったということのようです。
このように、整数型を大きさごとに多重定義するのは難しいようです。
スポンサード リンク |
面白い問題ですね。
関数テンプレート+SFINAEを使って対策できますよ。
Qiitaへ投稿しました。
http://qiita.com/Chironian/items/128e480d0ef8cfcbb00e