18
14

More than 5 years have passed since last update.

[c++]テンプレート関数の定義と実装はまとめてヘッダファイルに書かなければいけない

Last updated at Posted at 2015-06-04

[c++]テンプレート関数の定義と実装はまとめてヘッダファイルに書かなければいけない

(備忘録です.もっとうまいやり方があったら教えてください...)

関数の定義は「ヘッダファイル」,実装は「cppファイル」に記述するというような場合が結構あると思います.
しかし,テンプレート関数の場合,定義と実装は「ヘッダファイル」と「cppファイル」に分離できないようです.

ダメな例

hoge.h
class Hoge{
 public:
  template <class T> void func1(T val);
};
hoge.cpp
#include <iostream>
#include "hoge.h"

template <class T>
void Hoge::func1(T val){
  std::cout << "func1" << std::endl;
}
main.cpp
#include "hoge.h"

int main(){
  Hoge h;
  h.func1(1);
  h.func1("test");
}

結果

$ g++ -o hoge.exe hoge.cpp main.cpp
main.cpp: In function ‘int main()’:
main.cpp:5: error: no matching function for call to ‘Hoge::func1()’

と出る.

解決策

ヘッダに実装も書く.

一応,定義とは分離させて以下のように書いた.

hoge.h
#include <iostream>

class Hoge{
 public:
  template <class T> void func1(T val);
};

template <class T>
void Hoge::func1(T val){
  std::cout << "func1" << std::endl;
}
main.cpp
#include "hoge.h"

int main(){
  Hoge h;
  h.func1(1);
  h.func1("test");
}

結果

$ g++ -o hoge.exe main.cpp
$ ./hoge.exe
func1
func1

明示的実体化による解決

テンプレートの実装をヘッダに書かなければならない理由 - (void*)Pないと: http://d.hatena.ne.jp/pknight/20090826/1251303641
によると,
コンパイルの時点でテンプレート関数が一回も実体化されていないのが問題らしい.

そこで予め使われる型を使って実体化しておくと実行できる.

hoge.h
class Hoge{
 public:
  template <class T> void func1(T val);
};
hoge.cpp
#include <iostream>
#include "hoge.h"

template void Hoge::func1(int val);
template void Hoge::func1(char const* val);

template <class T> void Hoge::func1(T val){
  std::cout << "func1" << std::endl;
}
main.cpp
#include "hoge.h"

int main(){
  Hoge h;
  h.func1(1);
  h.func1("test");
}

結果

$ g++ -o hoge.exe hoge.cpp main.cpp
$ ./hoge.exe
func1
func1

しかし,明示的実体化は予め使われる型の関数宣言が必要なので,新しい型(特にユーザ定義型)が追加される場合は対応できない!

18
14
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
14