
こんにちは。
今回は、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で質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 MACアドレス
-
atlbase.h と afxwin.hの同時定義
-
vectorのイテレータを大小比較...
-
snprintfが使用できない。
-
gccでコンパイル時のエラー
-
C言語のエラーを修正したい
-
C++で、環境変数の読み込み方を...
-
boost::formatの値をstring型に...
-
switch文のエラーについて
-
CComBSTR型文字列の
-
VHDLのsignedとunsignedの違いは?
-
CStringとString
-
リモートデスクトップの接続元I...
-
最早開始時間と最遅完了時刻を...
-
信頼区間の1.96や1.65ってどこ...
-
Aの値からBの値を除するとは??
-
strncpyと_tcsncpy_sのヌルの扱...
-
プログラムでの数字につく”f”の...
-
gcc: incompatible pointer type
-
CStringのFindで文字列検索を行...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VC++で文字列から任意の文字を...
-
C++でShowCursorを使いたい。
-
enumの値から定義名を文字列化...
-
空ENTERの判別
-
VxWorks 6.4ソケット接続につい...
-
C++で、テキストファイルを一行...
-
switch文のエラーについて
-
_tcscat がうまくいきません(V...
-
C言語からgnuplot呼び出し
-
C言語のエラーを修正したい
-
std::map の const 修飾について
-
なぜ、C++の標準ヘッダをインク...
-
vc++の使い方について
-
gccでコンパイル時のエラー
-
このプログラミング誰か教えて...
-
STLでポインタのリストをsort()...
-
構造体配列のvectorへの変換と...
-
#defineの使い方について
-
#define中の#のエスケープ
-
リモートデスクトップの接続元I...
おすすめ情報