TopC++ 入門 › エラー辞典 › テンプレート

テンプレートエラー解読辞典

C++ のテンプレートエラーは時に 100 行を超え、初見では目眩がします。でも読み方のコツを押さえれば 3 秒で原因が分かります。このページではパターン 6 つで「どこを見る / 何を直す」を体得します。

1. 読み方の 3 ステップ

1
最初の "error:" 行だけ見る。以降は note(補足)なので無視可。
2
required from と書かれた行で「誰が呼び出して死んだか」をたどる。自分のコードの行が見つかる。
3
型名を短縮: std::__1::basic_string<char, std::__1::char_traits<char>, ...>std::string。脳内で置換する。
オプション: GCC は -fdiagnostics-show-template-tree で木構造に、clang は -fdiagnostics-format=fixit で簡潔に表示。普段使うと幸せ。

2. パターン 1 — "invalid use of incomplete type"

型の中身が見えていない時」に出る。前方宣言だけだと未完成型。

in file included from ...: error: invalid use of incomplete type 'class Widget' note: forward declaration of 'class Widget'
ng.cppNG
class Widget; // 前方宣言のみ void f(Widget* w) { w->show(); } // ← 中身が見えない
ok.cppOK
#include "widget.h" // ← 完全型が見える void f(Widget* w) { w->show(); }

3. パターン 2 — sort が要求する operator< が無い

std::sort に渡す要素型に< 比較が無いと、30 行超のエラーが出ます。読むべきは最後の方:

In file included from <algorithm>:60: In instantiation of 'void std::sort(_It, _It) [...]': required from here: main.cpp:12:5: required from here error: no match for 'operator<' (operand types are 'const Point' and 'const Point')
ng.cppNG
struct Point { int x, y; }; std::vector<Point> v; std::sort(v.begin(), v.end()); // ← < が無い
ok.cppOK
std::sort(v.begin(), v.end(), [](const Point& a, const Point& b){ return a.x < b.x; }); // または Point に operator< を定義
読みのコツ: "no match for 'operator<'" だけ拾えば十分。「なぜ呼ばれた?」は required from here の上を見る。

4. パターン 3 — map<Key, V> の Key に比較が無い

ng.cppNG
std::map<Point, int> m; m[{1,2}] = 0; // Point に < 無し
ok.cppOK
struct PointCmp { bool operator()(const Point& a, const Point& b) const { return std::tie(a.x,a.y) < std::tie(b.x,b.y); } }; std::map<Point, int, PointCmp> m;

5. パターン 4 — "candidate template ignored: could not match"

関数テンプレートの引数型が合わない時の定番。

error: no matching function for call to 'max' note: candidate template ignored: could not match 'T' against 'int' and 'double'
ng.cppNG
std::max(3, 4.5); // int と double、T が 1 つに決まらない
ok.cppOK
std::max<double>(3, 4.5); // 明示 std::max(3.0, 4.5); // 揃える

6. パターン 5 — constexpr / static_assert 違反

error: static_assert failed due to requirement 'std::is_integral_v<T>' "T must be integral"

テンプレートが型に要件を課しているときのエラー。どの要件を満たせばよいかが ""(文字列)に書かれている。

7. パターン 6 — 型名が爆発する「スパゲッティ型」

In instantiation of 'class std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(const char*)': required from 'void print(std::__1::vector<std::__1::basic_string<...>>&)'

長大な型はエイリアスで読む: std::__1::basic_string<char,...>std::stringstd::__1::vector<string>std::vector<string>。この脳内変換だけで 90% 楽になります。

便利ツール: cppinsights.io はテンプレートを展開後の形で見せてくれる。std::optional や range-for がどう展開されるか分かる。

8. 実用Tip集

  • テンプレートエラーは最初の error 行だけ読む。残りは補足。
  • テンプレート関数は特殊化で具体型を出すとデバッグしやすい。f<int>()
  • C++20 concepts を使うと、テンプレートエラーが要件違反の 1 行になる。
  • static_assert で要件を明示しておくと、内部の長ったらしいエラーより自分のメッセージが先に出る。
  • エラーメッセージを全文 Google 検索する時は、型名(std::__1::...)を削って検索すると当たりやすい。