2009-09-19 11 views
62

¿Hay alguna razón específica para no tener el algoritmo std :: copy_if en C++? Sé que puedo usar std :: remove_copy_if para lograr el comportamiento requerido. Creo que viene en C++ 0x, pero un simple copy_if que toma un rango, un iterador de salida y un functor habría sido bueno. ¿Simplemente lo perdieron o hay alguna otra razón detrás de esto?¿Por qué no hay ningún algoritmo std :: copy_if?

+0

+1 Nunca pensé en eso. – AraK

+3

Se agregará al siguiente estándar. El borrador actual lo tiene bajo el capítulo 25.2.1 en la biblioteca de algoritmos. –

+0

Duplicado: http://stackoverflow.com/questions/794320/are-they-adding-copyif-to-c0x –

Respuesta

41

De acuerdo con "El lenguaje de programación C++" de Stroustrup, era solo una visión excesiva.

(como una cita, la misma pregunta contestada en impulsar las listas de correo-: copy_if)

+9

Como una actualización, el estándar C++ 11 ha corregido este descuido añadiendo un nuevo 'copy_if' Algoritmo: http://en.cppreference.com/w/cpp/algorithm/copy –

7

Multiplesourcesindicate que se dejó fuera de STL por accidente.

Sin embargo, no estoy seguro de si eso es un hecho o un mito que se autoperpetúa. Agradecería que alguien señalara una fuente más creíble que un enlace a una publicación aleatoria en Internet.

+3

Aquí hay una publicación no aleatoria en Internet, seleccionada sobre la base de que se trata de un correo electrónico de Stroustrup a la lista de correo de Boost: http://lists.boost.org/Archives/boost/2001/01/8030.php. Por supuesto, podría ser un fraude, o podría ser que el propio Stroustrup haya comprado el mito. Supongo que es posible que Stepanov en general pensara que era mejor tener 'remove_copy_if', y deliberadamente excluyó' copy_if' como redundante.Pero en serio, es claramente un error tener 'remove_copy_if' pero no' copy_if', si solo uno de gusto :-) –

27

BS dice que se olvidaron. Está en C++ 11. Sin embargo, puede usar remove_copy_if (que realmente se debería llamar copy_if_not) junto con not1 en su lugar.

+6

En mi opinión, siempre traduzco "remove_copy_if" a "copy_except" :) – StackedCrooked

+1

... siempre que esté dispuesto a aceptar ese estándar. :: not1 no es compatible con un puntero de función. (Como veo se ha discutido a continuación ...) –

7

Está muerto fácil de escribir su propio:

template <class InputIterator, class OutputIterator, class Predicate> 
OutputIterator copy_if(InputIterator first, InputIterator last, 
         OutputIterator result, Predicate pred) 
{ 
    return std::remove_copy_if(first,last,result,std::not1(pred)); 
} 

Editar: Esta versión funciona con todos los predicados:

template <class InputIterator, class OutputIterator, class Predicate> 
OutputIterator copy_if(InputIterator first, InputIterator last, 
         OutputIterator result, Predicate pred) 
{ 
    while(first!=last) 
    { 
    if(pred(*first)) 
     *result++ = *first; 
    ++first; 
    } 
    return result; 
} 
+2

Esto no es realmente correcto, como se señala en * STL * efectivo elemento 36, porque solo funciona en funtores adaptables. – rlbond

+0

parece que no es tan fácil, parece que su segundo intento devuelve el primer valor que coincide con el predicado, además, en mi humilde opinión, está un poco fuera de tema aquí – rotoglup

+0

rotoglup - Me temo que no sabe qué estas hablando de. 'resultado' es un OutputIterator. Probé este código, ya sabes. –

9

simplemente para la corrección, en caso de que alguien googles su/su manera de esta pregunta, se debe mencionar que ahora (después de C + + 11) hay un algoritmo copy if. Se comporta como se esperaba (copia los elementos en un rango, para los cuales algún predicado devuelve verdadero, a otro rango).

Un caso de uso típico sería

std::vector<int> foo{ 25, 15, 5, -5, -15 }; 
std::vector<int> bar; 

// copy only positive numbers: 
auto it = std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar), 
      [](int i){return !(i<0); 
      }); 
1

simplemente para la corrección voy a añadir ese impulso tiene boost::algorithm::copy_if para aquellos de ustedes que no pueden utilizar C++ versión de 11 (como yo) en boost/algorithm/cxx11/copy_if.hpp que utilizará std::copy_if cuando :

#if __cplusplus >= 201103L 
// Use the C++11 versions of copy_if if it is available 
using std::copy_if;   // Section 25.3.1 
#else 

Ejemplo:

#include <boost/algorithm/cxx11/copy_if.hpp> 
#include <boost/assign/list_of.hpp> // for 'list_of()' 
#include <boost/foreach.hpp> 

#include <iostream> 
#include <vector> 
#include <iterator> 

struct Odd 
{ 
    bool operator()(int n) 
    { 
    return n & 1; 
    } 
}; 

int main() 
{ 
    std::vector<int> v = boost::assign::list_of(0)(1)(2)(3)(4); 
    BOOST_FOREACH(int i, v) 
    std::cout << i << ' ' ; 

    std::vector<int> out; 
    boost::algorithm::copy_if(v.begin(), v.end(), std::back_inserter(out), Odd()); 

    std::cout << std::endl; 

    BOOST_FOREACH(int i, out) 
    std::cout << i << ' ' ; 

} 

Salida:

0 1 2 3 4 
1 3 
Cuestiones relacionadas