
テンプレート関数でコンパイルが通りません
いつもお世話になってます。テンプレート関数XXXで、引数のTYPE型によって、XXX内で呼び出す関数が変わります。以下の例では、eTypeがAならSetADataを呼び、eTypeがBならSetBDataを呼び出します。XXXのもうひとつの引数がテンプレート部です。本当は、rInfoの型(AInfoまたはBInfo)を判別できればeTypeは不要なのですが、判別の仕方がわからないので、eTypeでrInfoの型を伝えるようにしています。
template<typename T> int XXX( T& rInfo, const TYPE& eType )
if( eType == A ){
SetAData( rInfo );
else if( eType == B ){
SetBData( rInfo );
}
// 明示的インスタンス生成
template int XXX<AInfo>( AInfo& rInfo, const TYPE& eType )
template int XXX<BInfo>( Binfo& rInfo, const TYPE& eType )
上記のようにした時、コンパイラはTの部分をAInfoとBInfoの両方で解釈するので、どうしても以下のようなコンパイルエラーが出ます。
---
`int XXX(T&, const TYPE&) [with T = AInfo]':
error: no matching function for call to `SetBData(AInfo&)'
note: candidates are: int SetBData(BInfo&)
`int XXX(T&, const TYPE&) [with T = BInfo]':
error: no matching function for call to `SetAData(BInfo&)'
note: candidates are: int SetAData(AInfo&)
XXXをテンプレート関数でなく、明示的にAInfoとBInfoのオーバーロードにする手もあるかもしれませんが、XXXの中で、ここには載せていない大多数の部分は、まったく同じなので、テンプレート関数にするのが筋かなと思っています。このコンパイルが通るようにするには、どうすれはよいのでしょうか。

No.4ベストアンサー
- 回答日時:
もしも、AInfo と BInfo が全く関連のない型であれば、 typeid で、クラス名を判別できますが……。
本当なら、オーバーロードが最適だと思います。
それも、この場合なら、XXX をオーバーロードするのではないです。
基本は、
class infoBase
{
virtual int XXX()
{
... いろいろな処理
setData();
... いろいろな処理
}
virtual void setData() = 0;
}
class AInfo : public infoBase
{
virtual void setData()
{ setAdata に相当する処理}
}
class BInfo : public infoBase
{
virtual void setData()
{ setBdata に相当する処理}
}
こんな感じで、XXX は、「論理的なひとつの関数」
setData は、「それぞれのデータに合わせて仮想化」
というのがシンプルで良いと思います。
ご回答、どうもありがとうございました。typeidというのがあるのですね。勉強します。データの方を継承クラスにする方法もあるのですね。今回は、AInfo とかBInfo は、中身が異なる小さな構造体なので、ここまではしない方針になりましたが、とても勉強になりました。
No.3
- 回答日時:
ごめんなさい。
なんか勘違いしてた。NO1は無視してください。さて、おっしゃるように、それぞれの処理の中で、双方同時に定義されていない関数を呼ぶと
コンパイルエラーになります。
解決策は「関数名を同じにすればよい」。
具体的には、次のソースの通りです。
#include <stdio.h>
class A{
public:
voidprint(){printf("A\n");};
};
class B{
public:
void print(){printf("B\n");};
};
void SetData(A){printf("SetA\n");}
void SetData(B){printf("SetB\n");};
template<typename T> int XXX(T& arg){
arg.print();
SetData(arg);
return 0;
};
int main(void){
A a;
B b;
XXX(a);
XXX(b);
return 0;
}
同名のメンバ関数を呼び出す、または引数が異なる関数を定義し、呼び出す。
質問者さんが書かれた、SetAData,SetBDataを、SetDataとすればたぶん全てがうまくいきます。
No.1
- 回答日時:
キーワードは「テンプレートの部分特殊化」
以下、サンプルソースです。
#include <stdio.h>
typedef unsigned long long A;
typedef unsigned short B;
template<typename T> int XXX(T& arg){
printf("ノーマル\n");
return 0;
}
// 以下、特殊化
template<> int XXX(A& arg){
printf("A\n");
return 0;
}
template<> int XXX(B& arg){
printf("B\n");
return 0;
}
int main(void){
A a;
B b;
int c;
XXX(a);
XXX(b);
XXX(c);
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
main.c:7:43: warning: implici...
-
DWORDの実際の型は何でしょうか
-
ハンドルされていない例外が発...
-
構造体を引数とする、クラス間...
-
sshdログの意味
-
void func( void )について
-
【#define】 defineで定義した...
-
プログラムの中で別のmainを呼...
-
typedefの使い方
-
C++のコンストラクタを宣言する...
-
24ビットの変数
-
2重定義って??
-
C言語のコンパイルエラー
-
相互参照するクラス、俺こんな...
-
最早開始時間と最遅完了時刻を...
-
20'(角度)の計算がわかりま...
-
信頼区間の1.96や1.65ってどこ...
-
Aの値からBの値を除するとは??
-
数字以外が入力されたらエラー...
-
値差の%計算方法について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
main.c:7:43: warning: implici...
-
long型の定数の末尾にLを付ける...
-
DWORDの実際の型は何でしょうか
-
visualstudio C# テキストボッ...
-
2重定義って??
-
C++のfor文について
-
変数の型を定義しなかった場合...
-
ハンドルされていない例外が発...
-
intとINTの違いは?
-
C++でboolにintの値を代入する...
-
構造体の要素すべてに対する四...
-
プログラムの中で別のmainを呼...
-
エラー「invalid conversion fr...
-
GCCで暗黙の型変換の警告を出し...
-
【#define】 defineで定義した...
-
sshdログの意味
-
DDVによるメッセージの変更
-
typedef enumの使い方を教えて...
-
構造体を生成時にわざわざ初期...
-
DLLでLIBファイルが作成されない
おすすめ情報