テンプレートの型推論失敗で no matching function になる原因
テンプレート関数の2つの引数に異なる型を渡したときに出るエラーです。同じ型パラメータTを2箇所で使うテンプレートは、呼び出し時にすべての箇所で矛盾なく同じ型が推論できなければコンパイルできません。
エラーメッセージの読み方
main.cpp:7:21: error: no matching function for call to 'add(int, const char [2])'
main.cpp- ファイル名
7- 行番号
21- 列番号 — この位置でg++が構文解析に失敗しました
no matching function for call to 'add(int, const char [2])'- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 #include <iostream> 2 template <typename T> 3 T add(T a, T b) { 4 return a + b; 5 } 6 int main() { 7 std::cout << add(3, "5") << std::endl; ^ 8 return 0; 9 }
同じ型パラメータTを2箇所で使うテンプレートは、両方の引数から矛盾なく同じ型が推論できないとコンパイルできません。3はint、"5"はconst char*で型が異なるため推論に失敗します。
直し方: "5" を 5 にします。
パターン2
1 #include <iostream> 2 template <typename T> 3 T maxOf(T a, T b) { 4 return a > b ? a : b; 5 } 6 int main() { 7 std::cout << maxOf(10, 3.5) << std::endl; ^ 8 return 0; 9 }
テンプレートは呼び出しごとに具体的な型を1つに確定できて初めてコンパイルが通ります。10はint、3.5はdoubleで型が異なるため、コンパイラはTを1つに決められません。
直し方: 3.5 を 3 にします。
パターン3
1 #include <iostream> 2 template <typename T> 3 T multiply(T a, T b) { 4 return a * b; 5 } 6 int main() { 7 std::cout << multiply(4, '2') << std::endl; ^ 8 return 0; 9 }
「テンプレートは何でも受け付けてくれる万能な関数」というのは誤解です。'2'はchar型であり、4のint型とは別の型として扱われるため型推論が失敗します。
直し方: '2' を 2 にします。
パターン4
1 #include <iostream> 2 template <typename T> 3 T sub(T a, T b) { 4 return a - b; 5 } 6 int main() { 7 std::cout << sub(9, "3") << std::endl; ^ 8 return 0; 9 }
9はint、"3"はconst char*で型が異なるため、Tを1つに決められません。
直し方: "3" を 3 にします。
パターン5
1 #include <iostream> 2 template <typename T> 3 T minOf(T a, T b) { 4 return a < b ? a : b; 5 } 6 int main() { 7 std::cout << minOf(7, 2.5) << std::endl; ^ 8 return 0; 9 }
7はint、2.5はdoubleで型が異なるため、テンプレートの型推論に失敗します。
直し方: 2.5 を 2 にします。
よくある誤解
「テンプレートは何でも受け付けてくれる万能な関数」というのは誤解です。テンプレートは呼び出しごとに具体的な型を1つに確定できて初めてコンパイルが通ります。引数ごとに異なる型を渡すと、コンパイラはTを1つに決められず型推論に失敗します。
実務での勘所
この種のエラーの直接的な直し方は2つあります。1つは、呼び出し時に山括弧で明示的に型を指定してmax<double>(a, b)のように書き、型推論そのものを行わせずTをdoubleに固定する方法です。もう1つは、呼び出し前に片方の引数を明示的にキャストして両方の型を揃える方法です。テンプレートは「型を自動で合わせてくれる」魔法ではなく、「呼び出し側が矛盾なく1つの型に決められること」を前提にした仕組みだと理解しておくと、エラーへの対処が早くなります。