Code Fix

中級

error: call of overloaded '...' is ambiguous の原因と直し方

同じ名前の関数が複数のオーバーロードを持ち、渡した引数の型からどちらを呼ぶべきかコンパイラが一意に決められないときに出るエラーです。

エラーメッセージの読み方

main.cpp:5:9: error: call of overloaded 'show(int)' is ambiguous
main.cpp
ファイル名
5
行番号
9
列番号 — この位置でg++が構文解析に失敗しました
call of overloaded 'show(int)' is ambiguous
内容 — 期待していたもの、または受け付けられなかったもの

このエラーが出る典型パターン

パターン1

 1  #include <iostream>
 2  void show(long x) { std::cout << "long:" << x << std::endl; }
 3  void show(unsigned long x) { std::cout << "unsigned long:" << x << std::endl; }
 4  int main() {
 5      show(5  );
              ^
 6      return 0;
 7  }
main.cpp:5:9: error: call of overloaded 'show(int)' is ambiguous

int型の5をlongに変換するかunsigned longに変換するかは同じ変換ランクで並んでしまい、コンパイラはどちらか一方を優先できません。リテラルにLを付けて型を明示します。

直し方: 55L にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  #include <iostream>
 2  void report(long x) { std::cout << "long:" << x << std::endl; }
 3  void report(unsigned long x) { std::cout << "unsigned long:" << x << std::endl; }
 4  int main() {
 5      report(10  );
                 ^
 6      return 0;
 7  }
main.cpp:5:11: error: call of overloaded 'report(int)' is ambiguous

「型が近ければコンパイラがうまく選んでくれる」というのは誤解です。曖昧な場合はエラーとして人間の判断に委ねられます。

直し方: 1010L にします。

この問題を解いてみる →

パターン3

 1  #include <iostream>
 2  void log_(long x) { std::cout << "long:" << x << std::endl; }
 3  void log_(unsigned long x) { std::cout << "unsigned long:" << x << std::endl; }
 4  int main() {
 5      log_(1  );
              ^
 6      return 0;
 7  }
main.cpp:5:9: error: call of overloaded 'log_(int)' is ambiguous

Lサフィックスを付けてリテラルの型そのものをlongにしてしまえば、変換の必要が無くなり曖昧さが解消します。

直し方: 11L にします。

この問題を解いてみる →

よくある誤解

「型が近ければコンパイラがうまく選んでくれる」というのは誤解です。C++のオーバーロード解決は複数の候補が同じ変換ランクで並んだ場合、どちらか片方を勝手に選ぶのではなく、エラーとして人間に判断を委ねます。

まとめ

error: call of overloaded '...' is ambiguousは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)