• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C++テンプレートでの引数)

C++テンプレートでの引数

このQ&Aのポイント
  • C++のテンプレートを使用して、引数に構造体を含める方法についてご質問いただきました。
  • 質問文章では、構造体を含んだテンプレート関数を使用して、構造体の要素を参照する方法についての具体的な例が示されています。
  • この方法を使って、C++のテンプレートを活用しながら構造体の要素を引数として受け取ることができます。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

>構造体のメンバ名は統一しないとダメみたいです。 はい、整合性のチェックというのはそれも含んだ意味です。 というより統一した構造体を複数作らないといけないなら 繰り返しになりますが、最初っから #include <stdio.h> template < class T > struct RECTEX { T x; T y; void Function() const { cout << x << endl; cout << y << endl; } }; int main(void){ RECTEX<int> t = {80,90}; RECTEX<double> r = {1.0,2.0}; t.Function(); r.Function(); return 0; } こういったソースにしてしまうのが最善解に思います。

DEADSPACE566
質問者

お礼

回答ありがとうございます。 構造体をテンプレート化してしまった方が扱いやすいということですね。

その他の回答 (7)

回答No.8

ここまでの文章から勘を働かせると おそらくCからC++に移行したばかりでご存知なかったのでは という気がしてきましたので、一応 C++ではstruct にも class にも 変数だけでなく関数も入れておくことができます。 struct A { int i; void IncrementI(){ ++i; } }; この、IncrementIをメンバ関数と呼びます。 A a; a.i = 7; //a.iは7 a.IncrementI(); //++a.iと同じ結果になり、a.iは処理後8に 「アクセス修飾子」とこの「メンバ関数」を組み合わせることによって 生のC言語と比べ、絶大に読みやすい(或いは保守・拡張が遥かに楽な) コードを作っていくことができます。 struct のデフォルトのアクセス修飾子はpublic class のデフォルトのアクセス修飾子はprivate になっていて、privateというのは、外部から直に触ることが出来ないということになっています。 class A { int i; //int型のメンバ変数をprivateで一つ持つ。 public: //この下の関数はpublicになります。 //クラス名(); は、「コンストラクタ」という初期化用のメンバ関数です。 A( int i_ ) : i(i_){} //上のメンバint i;を引数のi_で初期化します。 void IncrementI(){ ++i; } /* メンバ関数の()の後ろにconstを付けると,その関数中では特殊なことをしない限り メンバ変数は書き変えられる心配がありません。 */ int GetI() const { return i; } }; A a( 7 ); //コンストラクタに引数7を渡します。a.iは7になります。 a.IncrementI(); //a.iは8になります。 int k = a.GetI(); //kにa.iの現在の数値を代入します。 a.i = 0; /* これはエラー!privateなメンバに外から勝手にアクセスできません。コンパイルは失敗します。*/ こういう風にすることで、不必要なとこで間違って書き変えてしまう恐れを最小限にできるというわけです。

DEADSPACE566
質問者

お礼

回答ありがとうございます。 クラスのアクセス指定子で非公開、公開にできるんですよね。 C++なら構造体ではなくクラスを使うという方法の方がいいんでしょうね。

回答No.7

>ステップ数が多いと混乱の元なんでしょうかね。 そうですね。 よっぽど整理されたコードなら多少長くなってもその場その場での混乱が少ないですが 避けられる苦労ならわざわざ自ら選ぶことはありません。 >このxとyもテンプレート化したいといった事はできなんでしょうか? んん~~? どういう挙動がお望みなのでしょう? 下のコードでダメっていうのが逆にちょっと分かんない 間違ったコードでもいいので 理想をC++「っぽく」表せますか? ↓とりあえず現時点で、コレの真意、うまみ、骨の髄までしみ渡っていますか?  template < class T > struct RECTEX { T x; T y; void Function() const { std::cout << x << std::endl; std::cout << y << std::endl; } }; この場合の利点は Functionは「自分自身の構造体のメンバの名前」を使ってるだけなんで xやyって名前を間違う事は、打ち間違え以外にないだろうってとこにあります。 別の型を作りたかったら、簡単に作れますね RECTEX<double> a; RECTEX<int> b; RECTEX<short> c; RECTEX<long> d; メンバの名前を変えたければサクサクっと変えれますね template < class T > struct RECTEX { T 山田が光ると結果的に山田; T 伸びろ山田; void Function() const { std::cout << 山田が光ると結果的に山田 << std::endl; std::cout << 伸びろ山田 << std::endl; } }; これは普通のクラスや構造体とおんなじことです。 struct RECTEX { int a, b; void Function() const { std::cout << a << std::endl; //メンバを使うにはメンバ名が正しくないといけない。 std::cout << b << std::endl; } }; 逆にいえば、注意することはこれだけで済むという事です。

DEADSPACE566
質問者

お礼

詳しい解説ありがとうございます。 構造体の中の変数の型も自在に変えら得るようになれたらと思ったんです。 しかしそれでコードが複雑化するなら避けた方がいいと思いました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

「メンバへのポインタ」を使えばなんとかなるかと思ったけど, データメンバの場合には static じゃないとテンプレートの引数には渡せなさそう. とりあえず思い付くのは ・メンバへのポインタについてはテンプレートにするのをあきらめる ・必要なメンバをとりだす関数 (あるいはそのような機能を持つクラス) を作ってテンプレート引数に渡す くらい.

DEADSPACE566
質問者

お礼

回答ありがとうございます。 どうやらテンプレートのテンプレートとかは駄目みたいですね。

回答No.5

>ところで, stdio.h を #include しても cout は使えないような.... たぶん 省略されてるんじゃないでしょうかねw と、思って書いたんだけどもw 一応書くと #include <iostream> using namespace std; が、省略されてるはず、ってことでしょうね。 私的にはソースであってもグローバルに using namespace std; はさすがにちょっとお勧め致しかねますが。(小さいソースでは別にいいかもしれませんが) 関数内での using namespace std; cout, endl とかあるいは最初から std::cout, std::endl とかにする方が 副作用の恐れはだいぶ少ないでしょうね。

DEADSPACE566
質問者

お礼

回答ありがとうございます。 グローバルでの名前空間はしない方がいいとどこかのサイトで 観たことがあります。 ステップ数が多いと混乱の元なんでしょうかね。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

うぅ~ん, 「構造体のメンバ名は統一しないとダメ」ってのは当たり前だよねぇ. だって, 「の要素x」 とか言い切っちゃってるんだもの. まあこの辺はより具体的に「こんなことがしたい」というのが出てくればそれに合わせるんだけど. ところで, stdio.h を #include しても cout は使えないような....

DEADSPACE566
質問者

お礼

回答ありがとうございます。 x,yと記述したらそれに合わせなければならないんですね。 このxとyもテンプレート化したいといった事はできなんでしょうか? 質問を重ねるようですみませんが。

DEADSPACE566
質問者

補足

間違いでした。 #include <iostream> using namespace std; ですね。

回答No.2

こんばんは。 この場合だとこれで良いです。 template <class T> T Function(T abc){ cout << abc.x << endl; cout << abc.y << endl; return abc; } templateは使用箇所が出てくるまでコードの生成を遅延するという性質があります。 そして「その時に初めて整合性がチェック」されますのでこれで問題ありません。 (ただし型ごとに似たものが内部で作られるので、型が多いと実行ファイルサイズは膨張する可能性があります。) ただ、abcのコピーコンストラクタが無駄に呼ばれることになりますし この場合abcをそのまま返す理由もないので template <class T> void Function(const T& abc){ cout << abc.x << endl; cout << abc.y << endl; } こちらの方がよろしいかと思います。 ただ、この場合ですと structのメンバの型が違うだけですので クラスtemplateを使うのがよろしいかと思います。 ついでに C++ではtypedef struct {} 何々; としなくても struct 何々{}; だけで 何々 hoge; と使う事ができます。 以上を踏まえて、構造体の内部に持たせてしまう方法 template < class T > struct RECTEX { T x; T y; void Check() const { cout << x << endl; cout << y << endl; } }; で十分です。 この場合は int main(void){ RECTEX<int> t = {80,90}; RECTEX<double> r = {1.0,2.0}; t.Check(); r.Check(); return 0; } このような形になります。

DEADSPACE566
質問者

補足

 ありがとうございます。 さっそく試してみました。 構造体のメンバ名は統一しないとダメみたいです。 template <calss T> T Function(T abc) { // 構造体の要素にも対応している。 統一する cout << abc.x //の要素x << endl; cout << abc.y //の要素y << endl; return T; }

回答No.1

return T; を return abc; に変えたらどうでしょうか。

DEADSPACE566
質問者

お礼

回答ありがとうございます。 確かにその通りですね。 この場合 return T; です。

DEADSPACE566
質問者

補足

return T ではなくreturn abcでした。 すいません