2012-04-29 16 views
0

最初の質問stackoverflow :)私はC++に比較的新しいですし、テンプレートを使用したことがないので、もし私が何かばかげているなら私を許してください。私はリストを櫛形にし、一般的な型の特定の要素をチェックするテンプレート関数を持っています。そのようにして、文字列かintかなどを検索するかどうかを指定できます。テンプレート関数は、 "呼び出しに一致する関数がない"エラーを返します

template <class T> 
bool inList(T match, std::string list) 
{ 
    int listlen = sizeof(list); 
    for (int i = 0; i <= listlen; i++) { 
     if (list[i] == match) return true; 
     else continue; 
    } 
    return false; 
}; 

これは私のinList()への呼び出しです。

error: no matching function for call to 'inList(const char [5], std::vector<std::basic_string<char> >&)' 

私がやっている何を:私は次のエラーで平手打ちしています、コンパイル時に、私の失望と混乱を

if (inList<string>("test", testvec)) 
    cout << "success!"; 
else cout << "fail :("; 

testvecは、「テスト」を含むいくつかの要素を持つ文字列ベクトルであり、間違っている? :(

[EDIT] 私はテンプレート定義は、グローバル名前空間であることを言及することを怠っ。(:(どうやら、それは私のテンプレートが機能するかどうかを確認するための簡単なテストプログラムだし、そうでない)

答えて

4

これは、std :: vectorからstd :: stringに変換する方法がないためです。代わりに、コレクションの概念を抽象化する必要があります。

これを行うと、彼らはコレクションの 'コンセプト'に合っている限り、配列、ベクトル、文字列、リスト、デキューを使うことができます(ここでは、C++ 1xにはコンセプトが付いてくることを期待しています!)。自社でも使用できます特別に最適化されたコレクションタイプです。それはテンプレートの美しさです。

template<class elem_t, class list_t> 
bool in_list(const elem_t& elem, const list_t& list) { 
    for (const auto& i : list) { 
     if (elem == i) { 
     return true; 
     } 
    } 
    return false; 
} 

EDIT:C++ 11を使用して

(任意の標準のコレクション、プリミティブ配列、およびユーザー定義型で動作します)これは、テンプレートとしてのstd :: initializer_list推定する非標準の拡張機能です引数なので、明示的なオーバーライド提供:

template<class elem_t> 
bool in_list(const elem_t& elem, std::initializer_list<elem_t> list) { 
    for (const auto& i : list) { 
     if (elem == i) { 
     return true; 
     } 
    } 
    return false; 
} 

このバージョンでは、あなたはそれが好きで呼び出すことができます。

int main() { 
    std::vector<int> a = {1, 2, 3, 4, 5}; 
    std::cout << in_list(3, a) << std::endl; 
    std::string b = "asdfg"; 
    std::cout << in_list('d', b) << std::endl; 
    std::cout << in_list('d', "asdfg") << std::endl; 
    std::cout << in_list(3, {1, 2, 3, 4, 5}) << std::endl; 
    return 0; 
} 

まだC++ 98の人にとっては、これは文字列とベクトル、およびいくつかのユーザー定義型で動作します。しかし、それは生の配列では機能しません。

template<class elem_t, class list_t> 
bool in_list_98(const elem_t& elem, const list_t& list) { 
    list_t::const_iterator end = list.end(); //prevent recomputation of end each iteration 
    for (list_t::const_iterator i = list.begin(); i < end; ++i) { 
     if (elem == *i) { 
     return true; 
     } 
    } 
    return false; 
} 

それとも、あなたはSTLスタイルを行くことができます:

template<class elem_t, class iterator_t> 
bool in_list_stl(const elem_t& elem, iterator_t begin, iterator_t end) { 
    for (iterator_t i = begin; i < end; ++i) { 
     if (elem == *i) { 
     return true; 
     } 
    } 
    return false; 
} 
//call like std::string s = "asdf"; in_list_stl('s', s.begin(), s.end()); 

私はミスを犯した場合は、申し訳ありませんが、私は私のコンパイラが今実行している必要はありません...

+0

様々な良いです。簡単な答えは、文字列への変換を期待する文字列のベクトルの代わりに文字列を渡すことです。しかし、技術的には 'includes()'や 'find()'があります。 )自分で固体を書く必要はありません;) – chris

+0

私は私のページをリフレッシュする前に、私の質問に彼のコメントを削除したと思います。私は非常にばかげていると感じます。 'std :: vector 'を文字通り使うことができなかったので、 'inList()'の引数として 'std :: string'を引数として持っていました。私は 'std :: string'をベクターで使用したものだから使ってはいけないと思っていましたが、今はそれを愚かに見ています。**返信いただきありがとうございます。あなたの回答は今後の参考にも役立ちます。Robert:)** – ZeroKnight

+0

std :: includesまたはstd :: findを使用する場合は、end()に対してテストすることを忘れないでください。 in_list(a、b)== [](const auto&a、const auto&b){return std :: find(b.begin()、b.end()、a)!= b.end(); } - 私はラムダを抽象として、実際のコードとしてではなく、私たちが多形ラムダを持っていないことを知っています。それは今私たちがhaskellで残しておかなければならないものです。 –

関連する問題