【问题标题】:Generic function that receives different STL containers [C++]接收不同 STL 容器的通用函数 [C++]
【发布时间】:2020-08-02 17:56:30
【问题描述】:

我有一个关于 C++ 代码的问题。我的任务是创建一个通用函数来接收不同的 STL 容器(向量、列表、集合)并计算其中的奇数。

我的第一次尝试是:

template <typename T>
void countOdd(T x)
{
    int count = 0;
    for (int i = x.begin(); i < x.size(); i++)
        if (x % 2 == 1)
            count++;
    cout << count;
}

但是我遇到了很多错误,我认为这不是正确的方法。

【问题讨论】:

  • 请分享确切的编译器错误。 T 是什么?您是否缺少代码 sn-p 中的template&lt;typename T&gt;
  • 标准库中没有x.begin() 将为其返回int 的容器
  • x.begin() 返回一个迭代器而不是一个 int。 x 是容器,不是容器内的元素,不能对其执行 x%2

标签: c++ algorithm function generics stl


【解决方案1】:

你有很多问题。这个循环:

for (int i = x.begin(); i < x.size(); i++)

不正确。 begin() 返回一个迭代器,而不是一个索引。

还有这个条件:

if (x % 2 == 1)

不正确,因为x 是传入的范围,而不是单个元素。

最简单的方法是:

template<typename T>
void countOdd(T const & range)
{
    int count = 0;
    for (auto const &element : range)
        if (element % 2 != 0)
            count++;
    cout << count;
}

从 c++20 开始,你可以减少模板的样板并编写:

void countOdd(auto const & range)
{
    int count = 0;
    for (auto const &element : range)
        if (element % 2 != 0)
            count++;
    cout << count;
}

最后,你应该使用合适的算法,这样你就可以做到:

void countOdd(auto const & range)
{
  cout << std::count_if(std::begin(range), std::end(range),
                        [](auto element) { return element % 2 != 0; });
}

【讨论】:

  • 一个更加通用和高效的解决方案。虽然element % 2 == 1 当然也是错误的。 coliru.stacked-crooked.com/a/0fc813c36c65feb4
  • @Deduplicator 啊,好点,没有考虑负面因素。改为!= 0。谢谢指正。
【解决方案2】:

你需要template

然后更常见的属性是开始/结束而不是开始/大小(开始返回迭代器,而不是int

所以你可能会这样做

template <typename Container>
std::size_t countOdd(const Container& cont)
{
    return std::count_if(std::begin(cont), std::end(cont),
                         [](auto e){ return e % 2 != 0; });
}

【讨论】:

  • 感谢您的回复!我还在学习,它很有帮助!
【解决方案3】:

您应该实现的功能是std::count_if 的用例。来自cppreference的可能实现:

template<class InputIt, class UnaryPredicate>
typename iterator_traits<InputIt>::difference_type
    count_if(InputIt first, InputIt last, UnaryPredicate p)
{
    typename iterator_traits<InputIt>::difference_type ret = 0;
    for (; first != last; ++first) {
        if (p(*first)) {
            ret++;
        }
    }
    return ret;
}

标准算法将迭代器作为参数,容器提供方法来获取第一个元素 begin() 和最后一个元素 end() 的迭代器。

谓词是一个可调用的,它接受一个元素作为参数并返回一个bool 来指示是否应该计算该元素。

我们可以把它包装成一个以容器为参数的函数:

#include <iostream>
#include <algorithm>
#include <vector>

template <typename Container>
auto count_odds(const Container& c) {
    auto is_odd = [](auto element)->bool { return element % 2;};
    return std::count_if(c.begin(),c.end(),is_odd);
}


int main() {
    std::vector<int> v{1,2,3,4};
    std::cout << count_odds(v);
}
    

【讨论】:

    猜你喜欢
    • 2013-04-10
    • 2011-10-17
    • 1970-01-01
    • 2011-02-07
    • 2012-11-12
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多