はじめに
この記事は初心者C++アドベントカレンダー10日目の記事です。
注意
この記事に書かれているのは、テンプレートのコードを書く時ではなく、使う時に気をつけることです。
というか、そもそも人によっては注意しなくてもひっかからなかったりします。
書いたコード
swap.cpp
template <class T>
void swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
swap.hpp
template <class T>
void swap(T& a, T& b);
main.cpp
#include <iostream>
#include "swap.hpp"
int main()
{
int a, b;
std::cin >> a >> b;
swap(a, b);
std::cout << a << " " << b << std::endl;
return 0;
}
使ったコマンドと結果
$ g++ -c swap.cpp
$ g++ -c main.cpp
ここまではちゃんとできた。
$ g++ main.o swap.o
main.o:main.cpp:(.text+0x41): undefined reference to 'void swap<int>(int&, int&)'
main.o:main.cpp:(.text+0x41): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `void swap<int>(int&, int&)'
collect2: error: ld returned 1 exit status
は????
エラーの原因
$ g++ -c swap.cpp
これだった。
テンプレートは宣言や定義だけじゃなくて実体も含めてオブジェクトファイルを作らないといけないから、main.cpp
にswap.cpp
の中身を突っ込む必要がある。
調べたら、ヘッダーの中で更に隠しヘッダーをインクルードすることで実装を隠すテクニックがあるんだとか。
こんな感じになるのかな?
swap.hpp
template <class T>
void swap(T& a, T& b);
#include "swap_implement.hpp"
swap_implement.hpp
template <class T>
void swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
特殊化とかすれば大丈夫なんだろうか…