クラステンプレート (C++をもう一度)
[最終更新] (2019/06/03 00:42:45)
最近の投稿
注目の記事

サンプルコード

my_class.h

#ifndef MY_CLASS_H_
#define MY_CLASS_H_

// 関数テンプレート https://www.qoosky.io/techs/22b50b7062 と同様、
// テンプレートは通常ヘッダファイルにすべてを記述する必要があります。
// ヘッダファイルでの using 使用は好ましくないため std::cout 等とします。

#include <iostream>

template <typename MY_TYPE>
  class MyClass
{
 public:
    MyClass(MY_TYPE val);
    MyClass(const MyClass& other); // コピーコンストラクタ

 public:
    void Say() const;

 private:
    MY_TYPE m_val;
};

template <typename MY_TYPE>
  MyClass<MY_TYPE>::MyClass(MY_TYPE val) :
    m_val(val)
{
    // m_val = val;  // とするよりもシンプル: https://www.qoosky.io/techs/3fef7fa668
}

template <typename MY_TYPE>
  MyClass<MY_TYPE>::MyClass(const MyClass& other)
  // MyClass<MY_TYPE>::MyClass(const MyClass<MY_TYPE>& other)  // の省略形
  // ↑コンパイラが古くなければ「MyClass<MY_TYPE>」以降の「MyClass」は
  // 「MyClass<MY_TYPE>」と解釈されます。
{
    // コピーするだけの例
    m_val = other.m_val;
}

template <typename MY_TYPE>
  void MyClass<MY_TYPE>::Say() const
{
    std::cout << "MyClass::Say, " << m_val << std::endl;
}

#endif // #ifndef MY_CLASS_H_

main.cpp

#include <iostream>
#include "my_class.h"
using namespace std;

int main() {

    // 関数テンプレートと異なり、型の自動判別は困難な場合
    // が多く、無効化されています。明記する必要があります。
    MyClass<int> obj(1);
    MyClass<int> objCopied = obj;
    obj.Say();
    objCopied.Say();

    return 0;
}

デフォルトテンプレート引数

関数テンプレートとは異なり、クラステンプレートにはテンプレート引数の既定値を記述できます。

my_class.h

#ifndef MY_CLASS_H_
#define MY_CLASS_H_

#include <iostream>

template <typename MY_TYPE = char>
  class MyClass
{
 public:
    MyClass(MY_TYPE val);

 public:
    void Say() const;

 private:
    MY_TYPE m_val;
};

template <typename MY_TYPE>
  MyClass<MY_TYPE>::MyClass(MY_TYPE val) :
    m_val(val)
{
}

template <typename MY_TYPE>
  void MyClass<MY_TYPE>::Say() const
{
    std::cout << "MyClass::Say, " << m_val << std::endl;
}

#endif // #ifndef MY_CLASS_H_

main.cpp

#include <iostream>
#include "my_class.h"
using namespace std;

int main() {
    MyClass<> ch(97);
    MyClass<int> i(97);
    ch.Say(); //=> MyClass::Say, a
    i.Say(); //=> MyClass::Say, 97
    return 0;
}

なお、デフォルトテンプレート引数が複数ある場合は以下のように既出のテンプレート引数の値に依存させることができます。

template <typename MY_TYPE = char, typename MY_TYPE_2 = MY_TYPE>
template < typename MY_TYPE = char, typename MY_TYPE_2 = MyOtherClassTemplate<MY_TYPE> >

その際、後者の例では ">" と ">" の間にスペースを入れて、コンパイラが演算子 ">>" と区別できる状態にする必要があります。

テンプレート引数にクラステンプレート

my_class.h

#ifndef MY_CLASS_H_
#define MY_CLASS_H_

#include <iostream>

template <template <typename, typename> class MY_TEMPL>
  class MyClass
{
 public:
    void SetShow();

 private:
    MY_TEMPL< int, std::allocator<int> > m_val;
};

template <template <typename, typename> class MY_TEMPL>
  void MyClass<MY_TEMPL>::SetShow()
{
    m_val.push_back(0);
    m_val.push_back(1);
    std::cout << "MyClass::SetShow(" << m_val.size() << ")" << std::endl;
}

#endif // #ifndef MY_CLASS_H_

main.cpp

#include "my_class.h"
#include <iostream>
#include <vector> // https://www.qoosky.io/techs/62846dd250
#include <deque> // https://www.qoosky.io/techs/9828f24f38
using namespace std;

int main() {
    MyClass<vector> objV;
    MyClass<deque> objD;

    objV.SetShow(); //=> MyClass::SetShow(2)
    objD.SetShow(); //=> MyClass::SetShow(2)

    objV.SetShow(); //=> MyClass::SetShow(4)
    objD.SetShow(); //=> MyClass::SetShow(4)

    return 0;
}

テンプレート引数に整数

my_class.h

#ifndef MY_CLASS_H_
#define MY_CLASS_H_

#include <iostream>
#include <algorithm>

template <int N> // double など小数は指定できない仕様 (環境によってはコンパイルできてしまう)
  class MyClass
{
 public:
    static const int SIZE = N; // 静的メンバ定数 https://www.qoosky.io/techs/fc41205299

 public:
    MyClass();

 public:
    void Show(int i) const;

 private:
    int m_intarr[SIZE];
};

template <int N>
  MyClass<N>::MyClass()
{
    std::fill_n(m_intarr, SIZE, 0);
}

template <int N>
  void MyClass<N>::Show(int i) const
{
    std::cout << m_intarr[i] << std::endl;
}

#endif // #ifndef MY_CLASS_H_

main.cpp

#include "my_class.h"
#include <iostream>
using namespace std;

int main() {
    MyClass<8> obj;

    for (size_t i = 0, size = MyClass<8>::SIZE; i < size; ++i) {
        obj.Show(i);
    }

    cout << MyClass<8>::SIZE << endl; //=> 8
    cout << MyClass<16>::SIZE << endl; //=> 16

    return 0;
}

特殊化

この続きが気になる方は

クラステンプレート (C++をもう一度)

残り文字数は全体の約 37 %
tybot
100 円
関連ページ
    サンプルコード #include <iostream> #include <string> // ← 関数テンプレートのため、という訳ではなく string を使用したいため。 using namespace std; // シンプルなテンプレート template <typename MY_TYPE> MY_TYPE MyFunc(MY_TYPE a) { return a *
    概要 配列のように複数の要素の入れ物として機能するクラスをコンテナとよびます。コンテナクラスには vector、list、queue/stack などがあります。それぞれのコンテナクラスはクラステンプレートとして提供されており、したがってヘッダファイルを include するだけで使用できます。ヘッダファイルにはコンテナクラスのクラステンプレートだけでなく、そのコンテナのイテレータクラスのクラス
    ラムダ式 (Java 8) import java.util.Arrays; import java.util.List; import java.util.function.Function; class Main { public static String myFunc(Function<String, String> callback) { return cal
    概要 Scala は JVM 上で動作するバイトコードにコンパイルできる言語です。JAVA よりも柔軟な記述ができます。事前にこちらからダウンロードおよびインストールしておいてください。基本的な文法をまとめます。 変数および定数 詳細は『Scala の型に関する知識』をご参照ください。 object HelloWorld { def main(args: Array[String]):