C++ 函数返回包含输入容器特定元素的容器

C++ 函数返回包含输入容器特定元素的容器,c++,stl,copy,C++,Stl,Copy,我有一个向量或列表,其中我只想将代码应用于特定元素。例如 class Container : public std::vector<Element*> 我编写了一个成员函数Get(),如下所示 template<typename Fn> auto Container::Get(const Fn& fn) const { Container output; std::copy_if(cbegin(), cend(), std::inserter(o

我有一个
向量
列表
,其中我只想将代码应用于特定元素。例如

class Container : public std::vector<Element*>
我编写了一个成员函数
Get()
,如下所示

template<typename Fn>
auto Container::Get(const Fn& fn) const {
    Container output;
    std::copy_if(cbegin(), cend(), std::inserter(output, output.end()), fn);
    return output;
}
从性能角度看:这是一个好方法吗?还是复制和删除会更好

template<typename Fn>
auto Container::Get(const Fn& fn) const {
    Container output(*this);
    output.erase(std::remove_if(output.begin(), output.end(), fn), end(output));
    return output;
}
模板
自动容器::Get(const-Fn&Fn)const{
容器输出(*此);
擦除(std::remove_if(output.begin()、output.end()、fn)、end(output));
返回输出;
}
还是有更好的方法

编辑:不同的例子 因为我前面的示例可以用更好的方式编写,所以让我们展示一个不同的示例:

while (!(container2 = container1.Get(IsSomething)).empty()&&TimesFooCalled<SomeValue)
{
    Container container3(container2.Get(IsSomething));
    if (!container3.empty()) {
        Foo(*container3.BestElement());
    } else {
        Foo(*container2.BestElement());
    }
}

while(!(container2=container1.Get(IsSomething)).empty()&&TimesFooCalled不回答您的直接问题,但请注意,您可以实现原始算法,而无需复制任何内容。如下所示:

bool found = false;
for (Element* const el: inputContainer) {
  if (IsSomething(el)) {
    found = true;
    [some stuff]
  }
}
if (!found) {
  for (Element* const el : inputContainer) {
    [some stuff]
  }
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
    // Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer), 
    [](Element const *item) {
        if(IsSomething(item)) {
            // Do something with item
            return true;
        }
        return false;
    }
));

不回答您的直接问题,但请注意,您可以在不复制任何内容的情况下实现原始算法。如下所示:

bool found = false;
for (Element* const el: inputContainer) {
  if (IsSomething(el)) {
    found = true;
    [some stuff]
  }
}
if (!found) {
  for (Element* const el : inputContainer) {
    [some stuff]
  }
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
    // Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer), 
    [](Element const *item) {
        if(IsSomething(item)) {
            // Do something with item
            return true;
        }
        return false;
    }
));

我通常使用的模式如下:

bool found = false;
for (Element* const el: inputContainer) {
  if (IsSomething(el)) {
    found = true;
    [some stuff]
  }
}
if (!found) {
  for (Element* const el : inputContainer) {
    [some stuff]
  }
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
    // Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer), 
    [](Element const *item) {
        if(IsSomething(item)) {
            // Do something with item
            return true;
        }
        return false;
    }
));
这通常已经足够好了,所以其他方法似乎有些过头了

为了获得更好的性能,最好不要从列表中复制或删除元素。根据我的经验,出于缓存原因,如果只查看一次列表,速度会更快。因此,下面是我将如何从列表中找到一个或另一个“最佳”值:

auto const isBetter = std::greater<Element>();
Element const * best = nullptr, const * alt_best = nullptr;

for(Element const * current : inputContainer) {
    if(IsSomething(current)) {
        if(!best || isBetter(*best, *current)) best = current;
    } else {
        if(!alt_best || isBetter(*alt_best, *current)) alt_best = current;
    }
}

if(best) {
    // do something with best
} else if(alt_best) {
    // do something with alt_best
} else {
    // empty list
}

我通常使用的模式如下:

bool found = false;
for (Element* const el: inputContainer) {
  if (IsSomething(el)) {
    found = true;
    [some stuff]
  }
}
if (!found) {
  for (Element* const el : inputContainer) {
    [some stuff]
  }
}
for(auto const * item : inputContainer) if(IsSomething(item)) {
    // Do stuff with item
}
inputContainer.erase(std::remove_if(std::begin(inputContainer), std::end(inputContainer), 
    [](Element const *item) {
        if(IsSomething(item)) {
            // Do something with item
            return true;
        }
        return false;
    }
));
这通常已经足够好了,所以其他方法似乎有些过头了

为了获得更好的性能,最好不要从列表中复制或删除元素。根据我的经验,出于缓存原因,如果只查看一次列表,速度会更快。因此,下面是我将如何从列表中找到一个或另一个“最佳”值:

auto const isBetter = std::greater<Element>();
Element const * best = nullptr, const * alt_best = nullptr;

for(Element const * current : inputContainer) {
    if(IsSomething(current)) {
        if(!best || isBetter(*best, *current)) best = current;
    } else {
        if(!alt_best || isBetter(*alt_best, *current)) alt_best = current;
    }
}

if(best) {
    // do something with best
} else if(alt_best) {
    // do something with alt_best
} else {
    // empty list
}

您需要
back\u插入器
output.end()
将在插入第一个元素后立即失效。如果您想要性能,我建议您选择Yes。它适用于任何提供
push_-back
方法的东西。
std::vector
std::list
都可以。对容器进行子类化是一个好主意吗?我认为这不是一个好主意@JHBonarius请看我的扩展答案。您需要
返回\u插入器
输出。结束()
将在插入第一个元素后立即失效。如果您想要性能,我建议您选择Yes。它适用于任何提供
push_-back
方法的东西。
std::vector
std::list
都可以。对容器进行子类化是一个好主意吗?我认为这不是一个好主意@JHBonarius请看我的延伸回答。