0

みんな!

UpdateValue という名前のテンプレート関数があります。これは、整数、BOOL、文字列などのさまざまな型の値を更新するように設計されています。参照用に次のコード スニペットを参照してください。

#include <typeinfo.h>

template<class T> 
void UpdateValue(T Value)
{   
    if ( typeid(int) == typeid(Value) ) 
    {  
       ZOrder(Value);
    }
    else if ( typeid(bool) == typeid(Value) )
    {  
       BOOL bShow = Value ? TRUE : FALSE;
       Show(bShow);
    }
    else if ( typeid(CString) == typeid(Value) )
    {  
       Theme(Value);
    }
}

void Show(BOOL bShow) { m_bShow = bShow; }
void ZOrder(int nZOrder) { m_nZOrder = nZOrder; }
void Theme(CString strTheme) { m_strTheme = strTheme; }

BOOL m_bShow;
int m_nZOrder;
CString m_strTheme;

しかし、次のステートメントを使用してこの種のテンプレート関数を呼び出すと、

CString strValue = _T("Animal");
UpdateValue<CString>(strValue);

前述のコードは、次の例外をスローしてコンパイルに失敗しました。

e:\dynaprop\dynaprop\mainfrm.cpp(269): エラー C2664: 'CMainFrame::ZOrder': パラメーター 1 を 'CString' から 'int' に変換できません 1> これを実行できるユーザー定義変換演算子がありません1> e:\dynaprop\dynaprop\mainfrm.cpp(67) : 関数テンプレートのインスタンス化 'void CMainFrame::UpdateValue(T)' への参照を参照してください 1> with 1> [ 1> でコンパイルされますT=C文字列 1> ]

解き方を教えてください。前もって感謝します!

4

5 に答える 5

1

テンプレート機能を実際に使用していません。というか使い逃します。get インスタンス化を呼び出すと、ZOrder(Value)getsがvoid UpdateValue(T Value)出現するたびに、指定したようTに置き換えられCStringます。しかし、それだけです。

関数は次のようになります

void UpdateValue(CString Value)
{   
    if ( typeid(int) == typeid(Value) ) 
    {  
       ZOrder(Value);
    }
    else if ( typeid(bool) == typeid(Value) )
    {  
       BOOL bShow = Value ? TRUE : FALSE;
       Show(bShow);
    }
    else if ( typeid(CString) == typeid(Value) )
    {  
       Theme(Value);
    }
}

テンプレートがインスタンス化された後、通常のコンパイルが行われます...そしてエラーが発生ZOrder(Value);valueますCString。このような場合、RTTI を使用してこの呼び出しパスに到達することはありませんが、これによりエラーが発生します。

あなたがすべきことは、特殊化を使用してさまざまなタイプを処理することです。UpdateValueの元の定義を次のように置き換えてみてください。

template<> // specialization when T is get to be int
void UpdateValue<int>(int Value) { ZOrder(Value);};

template<> // specialization when T is get to be CString
void UpdateValue<bool>(bool Value) { BOOL bShow = Value ? TRUE : FALSE; Show(bShow);};

template<> // specialization when T is get to be CString
void UpdateValue<CString>(CString Value) { Theme(Value);};

template<class T>  //general case
void UpdateValue(T Value) { cout << "IMPLEMENT ME\n";};

次に、呼び出すときにUpdateValue< T >、適切な本体でバージョンを呼び出します。また、RTTI を使用する必要はありません。

更新: コメンターの提案の後。一般的なケース (つまり、未知の型) を処理する必要がない/処理したくない場合は、単純なオーバーロードに頼って、次のようにすることができます。

//Value is int
void UpdateValue(int Value) { ZOrder(Value);};
//Value is bool
void UpdateValue(bool Value) { BOOL bShow = Value ? TRUE : FALSE; Show(bShow);};
//Value is CString
void UpdateValue(CString Value){ Theme(Value);};

その場合、テンプレートさえ必要ありません!

于 2012-09-26T16:27:52.347 に答える
0

以前の回答とコメントで述べたように、式UpdateValue<CString>(CString)をコンパイルできなかったため、インスタンス化は失敗しますZOrder(CString)。テンプレートのインスタンス化は、実行時ではなく、コンパイル時の型の置換にすぎないことを忘れないでください。実行時RTTIとテンプレートを混在させることはお勧めできません。また、テンプレートが誤用されているように見えます。

テンプレートの代わりに関数のオーバーロードを使用することをお勧めします。同じ結果が得られます。

void UpdateValue(int Value)
{
    ZOrder(Value);
}     

void UpdateValue(bool Value)
{
   BOOL bShow = Value ? TRUE : FALSE;        
   Show(bShow);     
}

void UpdateValue(const CString& Value)
{
   Theme(Value);
} 
于 2012-09-26T16:37:53.970 に答える
0

他のいくつかの回答で述べられている (または暗示されている) ように、3 つのコード ブランチを 3 つのテンプレートの特殊化 (パラメーターの型ごとに 1 つ) に分ける必要があります。しかし、これはばかげています。UpdateValue引数の型に応じて 3 つの異なることを行う1 つの関数が本当に必要な場合UpdateValueは、テンプレートをまったく使用せずに、 3 つのオーバーロードを記述します。

(これは、BOOLタイプを使用しても機能しない可能性があります。これは、おそらく同様であるためです。別の方法を実行する非常に強力な (そして奇妙な) 理由がない限り、代わりにint使用する可能性が最も高いはずです。)bool

于 2012-09-26T16:34:50.413 に答える
0

You could use function overloading to achieve what you're trying to do I think, (I changed it to use STL string so I can get it compiling):

#include <typeinfo>
#include <string>

using namespace std;

bool m_bShow;
int m_nZOrder;
string m_strTheme;

void Show(bool bShow) { m_bShow = bShow; }
void ZOrder(int nZOrder) { m_nZOrder = nZOrder; }
void Theme(string strTheme) { m_strTheme = strTheme; }

void DoUpdate( bool bShow )
{
    Show( bShow );
}

void DoUpdate( int nZOrder )
{
    ZOrder( nZOrder );
}

void DoUpdate( string strTheme )
{
    Theme( strTheme );
}

template<class T>
void UpdateValue(T Value)
{
    DoUpdate( Value );
}

int main( int argc, char **argv )
{
    string strValue = "Animal";
    UpdateValue<string>(strValue);

    return 0;
}
于 2012-09-26T16:34:53.377 に答える
0

デッド コードであっても、コードはまだコンパイルされています。だからあなたが言うところ:

if ( typeid(int) == typeid(Value) )
{  
   ZOrder(Value);
}

実行されなくてもコードをコンパイルしようとするため、エラーがスローされます。

テンプレートの特殊化を使用することをお勧めします。

template<class T> 
void UpdateValue(T Value) {
    // By default, do nothing.
}

void UpdateValue < int >(int value) {
    ZOrder(value);
}

void UpdateValue < bool >(bool value) {
    BOOL bShow = Value ? TRUE : FALSE;
    Show(bShow);
}

void UpdateValue < CString >(CString value) {
    Theme(value);
}

これはテンプレートの不必要な使用です。代わりに、いくつかのオーバーロードを使用することをお勧めします。

于 2012-09-26T16:56:09.067 に答える