定义一个函数,使其可以接受列表或向量

问题描述 投票:2回答:2

我有一个函数需要接收std::liststd::vector MyClass *对象,并根据里面的内容做一堆处理。我不想复制函数体。

我只需要使用这些对象迭代它们并进行一些只读检查。

我曾想过直接传递.begin().end()迭代器,但这看起来并不漂亮。

有没有更好的解决方法,目前我有以下解决方案(从传递的向量创建另一个列表,这也不是理想的)。

void process(std::list<MyClass*> input)
{
    //A lot of processing
    BOOST_FOREACH(MyClass* itMyClass, input)
    {
        //some checks, creating new list based on the checks      
    }
    //A lot of processing
}
void process(std::vector<MyClass*> input)
{
    process(std::list<MyClass*>(input.begin(), input.end()));
}

编辑:

似乎很多人建议去begin()end(),我已经让它以类似于下面的例子的方式工作了。谢谢你的帮助。

//This one is private
template <typename Iterator>
void process(Iterator begin, Iterator end)
{
    //A lot of processing
    for (; begin != end; ++begin) 
    {
        //some checks, creating new list based on the checks
    }
    //A lot of processing
}
void process(std::list<MyClass*> input)
{
    process(input.begin(), input.end());
}
void process(std::vector<MyClass*> input)
{
    process(input.begin(), input.end());
}
c++ stl
2个回答
4
投票

您可以使用function template

template<class ListOrVector>
void process(ListOrVector const& input) {
    //your code
}

//You can also use a template template parameter
template<template<class My, class Alloc = std::allocator<My>> class ListOrVector>
void process(ListOrVector<MyClass*, Alloc> const& input) { ... }

请注意,我通过const引用(The const &)获取ListOrVector。这样可以防止复制。

编辑

我修复了第二个例子。缺少ListOrVector之前的qazxswpo,默认情况下分配器是class


0
投票

就像普通函数一样,函数模板也可以重载,这样你就可以充分利用这两个方面:基于迭代器的算法可以提供更大的灵活性,基于容器的算法更易于使用。

这样,您可以使用基于迭代器的重载来处理容器的子范围,使用基于容器的重载来处理容器的所有元素。


std::allocator<My

我建议首先定义一个函数模板process(first, last),它为你想要处理的元素序列采用迭代器对:

process()

这是一个基于迭代器的算法(即,它需要一个迭代器对),并且对应于STL算法遵循的相同方法。


template<typename Iterator> void process(Iterator begin, Iterator end) { for (auto it = begin; it != end; ++it) { // ... } }

然后,我将定义另一个重载第一个的函数模板process(container)。这个重载需要一个容器,并在传递的容器的元素上调用基于迭代器的process()版本:

process()

这是一个基于容器的算法,因为它需要一个容器。


这样,您可以使用基于容器的算法而不是基于迭代器的算法:

template<typename Container>
void process(Container const& c) {
   process(std::begin(c), std::end(c));
}

这个算法与要处理的容器分离(例如,它甚至可以用于C风格的数组,如你所见),但你直接在容器上调用它而不是传递迭代器。

当你不想处理容器的所有元素,而只是处理容器中的元素的子范围时,你总是可以调用带有迭代器对而不是容器的std::vector<int> vec{1, 2, 3}; std::list<int> lst{1, 2, 3}; std::array<int, 3> arr{1, 2, 3}; int carr[] = {1, 2, 3}; process(vec); process(lst); process(arr); process(carr); 的重载。

© www.soinside.com 2019 - 2024. All rights reserved.