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()です。testvec"test" を含むいくつかの要素を持つ文字列ベクトルです。

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

残念なことに、コンパイルすると、次のエラーが表示されます。

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

私は間違って何をしていますか? :(

[編集] テンプレート定義がグローバル名前空間にあることを忘れていました。(これは、私のテンプレートが機能するかどうかを確認するための簡単なテスト プログラムですが、機能しないようです :( )

4

1 に答える 1

4

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

これを行うことで、ユーザーは任意のコレクション タイプを渡すことができます。コレクションの「概念」に適合する限り、配列、ベクトル、文字列、リスト、deque を使用できます (ここでは、c++1x に概念が付属していることを願っています)。社内で特別に最適化された独自のコレクション タイプを使用することもできます。それがテンプレートの美しさです。

C++11 を使用する (すべての標準コレクション、プリミティブ配列、およびユーザー定義型で動作します):

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;
}

編集: 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());

間違いを犯した場合は、申し訳ありませんが、現在コンパイラを実行していません...

于 2012-04-29T03:44:50.617 に答える