質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

2155閲覧

c++でtemplate classのコンストラクタやメンバ関数を別ファイルで定義したい

GAKU_SAY

総合スコア23

コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/06/29 00:37

#質問を行う経緯

自作の行列演算を行うクラスの作成をしたいです.ただ,制作途中でコンストラクタ含めいろいろなところでエラーが発生したため解決案を知りたいです.

#コード

c++

1 2namespace MY_var{ 3template <class T, ssize_t row, ssize_t col> 4 using square_array = std::array< std::array<T, col> , row>; 5} 6 7/** matrix.hpp **/ 8template <ssize_t row, ssize_t col> 9class Matrix { 10 11 /** 行列 **/ 12 MY_var::square_array<double, row, col> matrix; 13 14 /** 行 **/ 15 int rows; 16 17 /** 列 **/ 18 int cols; 19 20public: 21 22 /** コンストラクタ **/ 23 Matrix(); 24 25 26 /** デストラクタ **/ 27 ~Matrix(); 28}; 29 30/** matrix.cpp **/ 31 32template <ssize_t row, ssize_t col> 33Matrix<row,col>::Matrix(){ 34 this->rows = row; 35 this->cols = col; 36} 37 38 39template <ssize_t row, ssize_t col> 40Matrix<row,col>::~Matrix(){ 41} 42 43/**main.cpp**/ 44 45int main(){ 46 47Matrix<1, 1> *a = new Matrix<1, 1>; 48 49delete a; 50 51return 0; 52}

#エラー内容

Undefined symbol: Matrix<1l, 1l>::Matrix()
Undefined symbol: Matrix<1l, 1l>::~Matrix()

#したいこと
コンストラクタや関数の定義はmatrix.cppで行いたいです.(matrix.hpp内で書く場合は動きます.)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

コンストラクタや関数の定義はmatrix.cppで行いたいです.

できません(やれんこともないけど極めて限定的)。

template <ssize_t row, ssize_t col>
Matrix<row,col>::Matrix() {...}

は、テンプレート引数 row, col が確定しないことにはコンパイルできませんから。

投稿2021/06/29 01:50

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

コンストラクタや関数の定義はmatrix.cppで行いたいです.

C++のテンプレートは、引数ごとに必要なクラスを生成するという形となっています。

そのため、「ヘッダにコードを書いて、使った側でどこでも実体化できるようにしておく」という仕組みを取らない場合、必要な引数を与えたクラスを、メソッドを定義したファイル内で実体化しておく必要があります。

ssize_tに与えられる数が固定的で何パターンかしかない、という状況でなければ、テンプレートとしての実用性が大きく制限されることとなります。

投稿2021/06/29 01:35

編集2021/06/29 01:36
maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GAKU_SAY

2021/07/01 04:23

非常にわかりやすかったです.ありがとうございます.
guest

0

ベストアンサー

テンプレートは実体化 (インスタンス化ともいう) という工程によって具体的な型にならないと使えません。 通常は暗黙の実体化と呼ばれる仕組みによって「使用されていたら実体化する」というルールです。 (複数の翻訳単位に同じ実体がある場合には統合されてひとつになる。) 使用する場所において定義が見えない場合には実体を作れないためにエラーになるのです。

同じ実体が各翻訳単位で作られる可能性があるのは無駄ではありますし、多少はコンパイル時間も伸びますので実体化を抑制する手段として extern template というものが用意されてはいます。 extern template で宣言すると「ここでは実体化しない」という意味になります。

ただ、 extern template で実体化を抑制してもプログラム全体のどこかでは実体が作られていないといけないことにはかわりないので他の翻訳単位で明示的実体化が必要です。 質問者の提示したコードを用いて例示すると以下のように書けます。 御覧の通り、必要となる実体を個別に実体化しなければならないのであまり使い勝手のよいものではないです。 よほど特別な事情がない限りテンプレートはヘッダファイルに書くものだと考えたほうがよいです。

cpp

1/**main.cpp**/ 2 3#include <cstddef> 4#include <array> 5#include "matrix.hpp" 6 7// Matrix<1, 1> の実体化をこの翻訳単位ではやらないという指示 8// 逆に言えば他の翻訳単位で実態化されていなければならない 9extern template class Matrix<1, 1>; 10 11int main(){ 12 Matrix<1, 1> *a = new Matrix<1, 1>; 13 delete a; 14 return 0; 15}

cpp

1/** matrix.hpp **/ 2 3#include <array> 4 5namespace MY_var{ 6template <class T, std::size_t row, std::size_t col> 7 using square_array = std::array< std::array<T, col> , row>; 8} 9 10template <std::size_t row, std::size_t col> 11class Matrix { 12 MY_var::square_array<double, row, col> matrix; 13 int rows; 14 int cols; 15public: 16 Matrix(); 17 ~Matrix(); 18}; 19

cpp

1/** matrix.cpp **/ 2 3#include <array> 4#include "matrix.hpp" 5 6template <std::size_t row, std::size_t col> 7Matrix<row,col>::Matrix(){ 8 this->rows = row; 9 this->cols = col; 10} 11 12template <std::size_t row, std::size_t col> 13Matrix<row,col>::~Matrix(){ 14} 15 16// Matrix<1, 1> に関してここで実態化しておくという明示的な指示 17template class Matrix<1, 1>;

投稿2021/06/29 02:15

SaitoAtsushi

総合スコア5686

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GAKU_SAY

2021/07/01 04:25

長文でわかりやすい解説と解決案を出してくださりありがとうございます. vectorを使用して作成しようと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問