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を付けて型を明示します。
直し方: 5 を 5L にします。
広告
広告スロット(未設定)
パターン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
「型が近ければコンパイラがうまく選んでくれる」というのは誤解です。曖昧な場合はエラーとして人間の判断に委ねられます。
直し方: 10 を 10L にします。
パターン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にしてしまえば、変換の必要が無くなり曖昧さが解消します。
直し方: 1 を 1L にします。
よくある誤解
「型が近ければコンパイラがうまく選んでくれる」というのは誤解です。C++のオーバーロード解決は複数の候補が同じ変換ランクで並んだ場合、どちらか片方を勝手に選ぶのではなく、エラーとして人間に判断を委ねます。
まとめ
error: call of overloaded '...' is ambiguousは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。