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

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

新規登録して質問してみよう
ただいま回答率
85.49%
C++

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

Q&A

解決済

1回答

237閲覧

C++のクラステンプレートのメンバ関数

TSH1984

総合スコア22

C++

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

0グッド

0クリップ

投稿2018/07/17 15:57

C++でテンプレートクラスを作成した際に,
voidのメンバ関数にもクラスのテンプレートを反映させる(?)方法がわかりません.

例えば,以下のようにtest.hppにプロトタイプ宣言されていて:

c++

1template<typename T, typename U> 2class hoge{ 3 public: 4 T num 5 U value 6 7 void input_data(char* filename) 8}

hoge.cppにて以下のようにメンバ関数を作って呼び出した場合,
"定義されていない参照です"というエラーが出ます

c++

1template<typename T, typename U> 2void hoge::input_data(char* filename){ 3 //..略.. 4 //templaeteで指定された型でファイルからデータを読み込む 5 //..略.. 6} 7 8int main{ 9 filename="a.txt" 10 class hoge<double, int> A; 11 hoge.input<double, int>(filename) 12}

inputではfprintfなどを行うフォーマット指定子がif文で区切られていて,引数や返り値には使わないのですが,クラスを宣言した時点で型を切り替えたいです.

できればmainのhogeクラスの生成時以降は<double, int>を書きたくないのですが,なにかいい方法はないでしょうか.
どなたか教えていただけたら幸いです.

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは。

input_data()関数の宣言が間違っています。
正しくは以下です。

C++

1template<typename T, typename U> 2void hoge<T, U>::input_data(char* filename){ 3 //..略.. 4 //templaeteで指定された型でファイルからデータを読み込む 5 //..略.. 6} 7 8int main{ 9 filename="a.txt" 10 class hoge<double, int> A; 11 A.input(filename) 12}

ただ、テンプレートのメンバ関数を例えば、foo.cppで定義し、それをbar.cppから呼び出す場合、foo.cppにて使用しうる全てのテンプレート・パラメータの組み合わせに対して明示的実体化する必要があります。
これが可能な場合もありますが、不可能なケースもあります。(例えば、テンプレート・パラメータにbar.cpp側で定義されたユーザ定義型を指定するような場合)
そのような場合は、ヘッダで定義してしまいます。

C++

1template<typename T, typename U> 2class hoge{ 3 public: 4 T num 5 U value 6 7 void input_data(char* filename){ 8 //..略.. 9 //templaeteで指定された型でファイルからデータを読み込む 10 //..略.. 11 } 12}

このあたりの仕様が決められる際にはかなりすったもんだしたそうです。
テンプレートの実体化の実装方法とODR違反についてが参考になると思います。

投稿2018/07/17 16:30

Chironian

総合スコア23272

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

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

TSH1984

2018/07/17 16:47

ありがとうございます.ひとまずコンパイルまで行きました. ちょっと質問が次のステップになってしまうのですが,実際は3つのテンプレート引数があり,{short, int, long} {short, int, long} {float, double}の組み合わせに対応しなければなりません. おっしゃる通り別のcppで実装してmainから呼ぶ予定で,全てのパターンを実装しなければならないのでしょうか. なにかラッパーなどを書いて上手くテンプレートで記述する方法があればご教授いただけないでしょうか.
Chironian

2018/07/17 16:53

input_data()関数を別cppで定義するなら、3x3x2=18通り明示的実体化しておくしかないです。 コンパイラはbar.cppをコンパイルしている時、foo.cppでどのような実体化がなされるのか把握できませんから、bar.cpp内で実体化されたものだけをマシン語へ落とすからです。 全ての組み合わせの明示的実体化するのは手間がかかりますから、回答に示したようにクラス内定義することが多いです。
TSH1984

2018/07/17 16:55

回答有り難うございます わかりました..諦めてクラス内実装することにします..(inputが100行くらいあるので,ちょっと嫌だったのですが..) 頑張ってみます.ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問