エラー「Implicit instantiation of undefined template」の原因

C++で特定のクラスを利用すると、稀に以下のようなエラーが発生する。

// Implicit instantiation of undefined template 'std::__1::array<int, 3>'
std::array<int, 3> ary;

原因

ヘッダーファイルがインポートされていないことが原因。クラスに対応するヘッダーをきちんとインポートすれば良い。

#include <array>
std::array<int, 3> ary; // OK

根本原因

クラスの定義が見つからないことが原因。

// error: implicit instantiation of undefined template 'std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >'
std::stringstream ss{};

std::stringstreamクラスなどはiosfwdヘッダファイル側でtypedefによる前方宣言がされているが、実際の実装はsstreamヘッダで定義されているので、そちらをインクルードする必要がある。

/* iosfwd.h */
typedef basic_stringstream<char> stringstream;

/* sstream.h */
template <class Char, class Traits, class Allocator>
class basic_stringstream : public basic_iostream<Char, Traits> {}
iosfwd内の前方宣言は主にヘッダーファイル側で利用することが想定されている。前方宣言のみをインクルードしたほうがコンパイル速度が早くなるためだ。sstreamやiostreams等の詳細なヘッダーファイルは、実装ファイル側でインクルードすればいい。逆にヘッダーファイル側で詳細なヘッダーファイルを読み込んでしまうと、それらのヘッダーファイル側に含まれる実装コードも余計にコンパイルされてしまうため、コンパイル速度の低下に繋がる。

同じようにstd::arrayクラスで以下のような、

No member named 'array' in namespace 'std'

というエラーにならないのは、arrayクラスが前方宣言されているため(標準ライブラリ側で暗黙的に前方宣言されている場合がある)

実際にMyArrayというクラスを前方宣言のみ行い、実体は未定義の状態でコンパイルしてみると、今回と同様のエラーが発生する。

// 前方宣言
template <class _Tp, size_t _Size> struct MyArray;
// 定義省略
// template <class _Tp, size_t _Size> struct MyArray {};

/// Implicit instantiation of undefined template 'MyArray<int, 3>'
MyArray<int, 3> ary;
広告