こんにちは。
今回は、C++ テンプレートで引数に構造体を使えないか悩んでいます。
例えば
#include <stdio.h>
typedef struct _rect{
int x;
int y;
}RECT;
typedef struct _rect{
double x;
double y;
}DATA;
template <calss T>
T Function(T abc)
{
// 構造体の要素にも対応している。
cout << abc//の要素x << endl;
cout << abc//の要素y << endl;
return T;
}
int main()
{
RECT t;
DATA r;
t.x = 80;
t.y = 90;
t = Function(t); // こういった事をしたい
r = Function(r);
return 0;
}
というふうにしたいんです。
テンプレート関数に引数として構造体にしてそれぞれの要素を参照する場合はどうすれば
よろしいのか教えてください。
よろしくお願いします。
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;
}
こういったソースにしてしまうのが最善解に思います。
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なメンバに外から勝手にアクセスできません。コンパイルは失敗します。*/
こういう風にすることで、不必要なとこで間違って書き変えてしまう恐れを最小限にできるというわけです。
回答ありがとうございます。
クラスのアクセス指定子で非公開、公開にできるんですよね。
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;
}
};
逆にいえば、注意することはこれだけで済むという事です。
詳しい解説ありがとうございます。
構造体の中の変数の型も自在に変えら得るようになれたらと思ったんです。
しかしそれでコードが複雑化するなら避けた方がいいと思いました。
No.6
- 回答日時:
「メンバへのポインタ」を使えばなんとかなるかと思ったけど, データメンバの場合には static じゃないとテンプレートの引数には渡せなさそう.
とりあえず思い付くのは
・メンバへのポインタについてはテンプレートにするのをあきらめる
・必要なメンバをとりだす関数 (あるいはそのような機能を持つクラス) を作ってテンプレート引数に渡す
くらい.
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
とかにする方が
副作用の恐れはだいぶ少ないでしょうね。
回答ありがとうございます。
グローバルでの名前空間はしない方がいいとどこかのサイトで
観たことがあります。
ステップ数が多いと混乱の元なんでしょうかね。
No.4
- 回答日時:
うぅ~ん, 「構造体のメンバ名は統一しないとダメ」ってのは当たり前だよねぇ. だって,
「の要素x」
とか言い切っちゃってるんだもの. まあこの辺はより具体的に「こんなことがしたい」というのが出てくればそれに合わせるんだけど.
ところで, stdio.h を #include しても cout は使えないような....
回答ありがとうございます。
x,yと記述したらそれに合わせなければならないんですね。
このxとyもテンプレート化したいといった事はできなんでしょうか?
質問を重ねるようですみませんが。
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;
}
このような形になります。
この回答への補足
ありがとうございます。
さっそく試してみました。
構造体のメンバ名は統一しないとダメみたいです。
template <calss T>
T Function(T abc)
{
// 構造体の要素にも対応している。 統一する
cout << abc.x //の要素x << endl;
cout << abc.y //の要素y << endl;
return T;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# C++のcinの動作 5 2023/02/26 00:13
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# C++初心者です stirng 2 2022/09/20 20:43
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
switch文のエラーについて
-
VC++で文字列から任意の文字を...
-
このプログラミング誰か教えて...
-
ファイル読み込みとmap処理
-
boost::lexical_castで16進数文...
-
enumの値から定義名を文字列化...
-
Linux Ubuntu19.10でQt5.14.1の...
-
ハミング符号の解読について
-
セグメンテーションフォルトが...
-
#include "fstream.h"
-
C言語からgnuplot呼び出し
-
vectorの中にmap
-
Haru PDF Library
-
C++で、テキストファイルを一行...
-
C言語のポインターで詰まっている
-
snprintfが使用できない。
-
winpcapを用いたプログラミング
-
C言語プログラミングにて、関数...
-
JPEGやPNGが読めるLoadImage関数
-
Vectorのポインタが入ったvector
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
構文エラーが出ているのですが...
-
VC++で文字列から任意の文字を...
-
enumの値から定義名を文字列化...
-
switch文のエラーについて
-
空ENTERの判別
-
なぜ、C++の標準ヘッダをインク...
-
【C++】ヘッダ内でstringを格納...
-
C++での <iostream.h>と<iostre...
-
#include "fstream.h"
-
#define中の#のエスケープ
-
JPEGやPNGが読めるLoadImage関数
-
リモートデスクトップの接続元I...
-
CStringとString
-
string型のフォーマット書式指...
-
std::map の const 修飾について
-
VHDLのsignedとunsignedの違いは?
-
このプログラミング誰か教えて...
-
構造体配列のvectorへの変換と...
-
指定した文字を削除したい
-
構造体に決められた文字列を入...
おすすめ情報