テンプレートエラー解読辞典
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::string。std::__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::...)を削って検索すると当たりやすい。