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。相反,您需要做的是对集合的概念进行抽象。

您这样做是为了让人们可以传入他们想要的任何集合类型。他们可以使用数组、向量、字符串、列表、双端队列……只要它符合集合的“概念”(希望 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 回答