いろきゅうの(元)はてなダイアリー

はてなダイアリーから移行中…

関数オーバーロードの失敗

テストでこんなコード書いてみました。 (見づらいらいなぁ…)

long double f(long double)  { return 0; }
double f(double) { return 0; }
float f(float) { return 0; }
UINT64 f(UINT64) { return 0; }
INT64 f(INT64) { return 0; }
ULONG f(ULONG) { return 0; }
LONG f(LONG)  { return 0; }
UINT f(UINT)  { return 0; }
INT  f(INT)  { return 0; }
USHORT f(USHORT) { return 0; }
SHORT f(SHORT) { return 0; }
UCHAR f(UCHAR) { return 0; }
CHAR f(CHAR)  { return 0; }
bool f(bool)  { return false; }
int main()
{
  f(3); // どこに飛ぶかな?
  getchar();
  return 0;
}

関数 f をオーバーロードして、f(3) としたとき、どれが呼ばれるかのテストですね。 まぁ、これは int f(int) が普通に呼ばれるので問題ないのです。

問題は、UINT 以下の関数をコメントアウトして未使用にした時なのです。つまり残る関数は

long double f(long double)  { return 0; }
double f(double) { return 0; }
float f(float) { return 0; }
UINT64 f(UINT64) { return 0; }
INT64 f(INT64) { return 0; }
ULONG f(ULONG) { return 0; }
LONG f(LONG)  { return 0; }

の7つ。
この時、 f(3) はどれが呼ばれるのか…と。

結論としては、コンパイルエラーでした。(苦笑
コンパイラ側としても、どの関数を読んでいいのかわからない模様。 LONG あたりが呼ばれるのかなー とか、思ったんですけどねぇ… う〜ん、意外でした。


ちなみに、何でこんな事やったかというと、整数型と浮動小数点型で違う関数が呼べないかなー って思ったんですよ。イメージ的にはこんな感じ。タグディスパッチっぽい感じ(?)ですかね。

__inline long double test_cast_(const A& a, long double)
{ // 浮動小数点であれば、こっち
  return 何か処理;
}

__inline UINT64 test_cast_(const A& a, UINT64)
{ // 整数型であれば、こっち
  return 何か処理;
}

template<typename T>
__inline T test_cast(const A& a)
{ // 普段はこいつを呼び出して、内部の test_cast_ で分岐
  T v;
  return static_cast<T>(test_cast_(a, v));
}

int main()
{
  A a;
  double d = test_cast<double>(a);
  int      n = test_cast<int>(a);
}



まぁつまりは「浮動小数点型 と 整数型 が判別できたら良いよな〜」ってことなんですが… 何か良い方法ってないものですかねぇ〜。