LoginSignup
9
8

More than 5 years have passed since last update.

templateを使う時にコケた話

Posted at

はじめに

この記事は初心者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.cppswap.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;
}

特殊化とかすれば大丈夫なんだろうか…

9
8
3

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
9
8