2009-06-27 4 views
5

テンプレート関数 "compare"が以下のように定義されています。テンプレートのインスタンシエーションエラー

#include<iostream> 
using namespace std; 

template<typename T> 
void compare(const T&a, const T& b) 
{ 
    cout<<"Inside compare"<<endl; 
} 

main() 
{ 
compare("aa","bb"); 
compare("aa","bbbb"); 
} 

同じ長さの文字列リテラルとの比較をインスタンス化すると、コンパイラは不平を言いません。異なる長さのリテラルでは、 "エラー:(const char [3]、const char [5])を比較する呼び出しに一致する関数がありません"というメッセージが表示されます。

私は、 文字配列ではなく、文字ポインタです。 文字列リテラルは常にポインタに崩壊してはいけませんか?

void compare(const T* a, const T* b) 

理由は、異なるサイズの文字配列の種類は実際には異なるタイプであるということです。

答えて

4

Gregの答えとコメントで述べたように、2つの異なる配列型(それ以来、文字列リテラルがあります)が問題です。ジェネリック型のままにしておきたいが、文字ポインタや配列のために関数をオーバーロードすることができます。これは、多少異なる扱い方をする場合に最も便利です。

void compare(char const* a, char const* b) { 
    // do something, possibly use strlen() 
} 

template<int N1, int N2> 
void compare(char const (&a)[N1], char const (&b)[N2]) { 
    // ... 
} 

あなたはその後、配列が自動的に変換され、明示的に文字ポインタを取るべきであるが、比較指定したい場合は、次の

compare<char const*>("aa", "bbbb"); 

一方、多分比較する二つの異なるタイプで動作するように書くことができます?これは他のタイプにも有効です(例:おそらく、a.size() < b.size()の場合はf(a)、それ以外の場合はf(b)fのオーバーロード)を呼び出します。 (T1とT2は同じタイプにすることができますが、これは上記の2つの関数の代わりに関数を置き換えます)。

template<typename T1, typename T2> 
void compare(T1 const& a, T2 const& b) { 
    // ... 
} 
6

あなたの例では、あなたが宣言を変更した場合コンパイルします。テンプレート関数内でsizeof(T)を使用した場合、コンパイラはあいまいさを解決する方法を知らないでしょう。上記の宣言では、文字列を渡すときにコンパイラがconst char*としてうまく解決するポインタ型のT型を持つテンプレート関数を呼び出しています。

+0

@Greg、現在の宣言の問題点は何ですか? – chappar

+0

書面による宣言では、関数のcompareにはまったく同じ型の2つのパラメータが必要です。 "const char [3]"と "const char [5]"は同じ型ではありません。 –

+0

既存のコードでは、 "compare"はvoid compare(char a [2]、char b [4])のように評価されます。参照の代わりにポインタを使うということは、2種類の大きさの配列(異なる型)ではなく、Tが安全に "char"と評価できることを意味します。 – Justicle

3

可能であれば、コンパイラは文字列リテラルを文字バッファとして解釈します。そうでなければ、const char *と解釈することができます。 しかし、コンパイラは、Tの最善の解釈を見つけるためにバックトラックを行うつもりはありません。それほど複雑ではありません。 Tがconst char [3]であると決定すると、それは動きます。 2番目の引数を評価すると失敗します。あなたはあなたが行ってもいいです

compare(static_cast<const char *>("aa"),static_cast<const char *>("bbbb")); 

でそれを呼び出した場合

+0

しかし、地獄のように読む: – xtofl

+0

( "aa"、 "bbbb")と比較し、テンプレート+オーバーロードの解像度はそれほど単純ではありません:( –

+0

テンプレートオーバーロードの解像度は単純ではなく、合意されていますが、 Tの型を推論するのに十分複雑なので、ここでは両方の変数を統一します。 –

関連する問題