2011-06-06 18 views
5

Estoy usando Boost.Filesystem para crear una lista de archivos en un directorio. Yo uso boost::filesystem::recursive_directory_iterator y std::copy para poner cada ruta en un std :: vector como un objeto boost::filesystem::directory_entry. Deseo de salida para el archivo como std :: cuerdas embargo, así que hice lo siguiente (\ n Para evitar el uso de < <):std :: transformar y mover la semántica

std::vector<boost::filesystem::directory_entry> buffer; //filled with paths 
... 
std::vector<std::string> buffer_native(buffer.size()); 
//transform directory_entry into std::string, and add a \n, so output is formatted without use of << 
std::transform(buffer.begin(),buffer.end(),buffer_native.begin(), [](boost::filesystem::directory_entry de)->std::string 
    { 
     std::string temp=de.path().string(); 
     temp+="\n"; 
     return temp; 
    } 
    buffer.clear(); 
    std::copy(buffer_native.begin(),buffer_native.end(),std::ostream_iterator<std::string>(out_file)); 

Sin embargo, el problema con esto es que se crean dos vectores, el el original se borra inmediatamente porque no es necesario. Esto suena como un lugar perfecto para la semántica de movimiento, pero n3242 solo proporciona las mismas dos sobrecargas de transformación que en C++ 98. ¿Es posible implementar la semántica de movimiento con std::transform? Si no es así, ¿sería mejor escribir un ciclo personalizado?

Estoy usando GCC 4.5.2 (MinGW) en Windows XP.

Respuesta

7

Esto se parece a un trabajo para make_move_iterator:

std::transform(make_move_iterator(buffer.begin()), 
       make_move_iterator(buffer.end()), buffer_native.begin(), 
       [](boost::filesystem::directory_entry&& de) -> std::string 
{ 
    // still makes copy :/ perhaps native() would work better, I don't know 
    std::string temp = de.path().string(); 
    temp += "\n"; 

    return temp; 
} 

Un movimiento iterador es simplemente un iterador que se mueve su resultado eliminar la referencia. Tenga en cuenta que la clase debe admitir la semántica de movimientos para que esto haga una diferencia; No sé si Boost FS lo hace.


Tenga en cuenta que si su objetivo es darles salida en líneas separadas, lo está haciendo mal. La impresión formateada no debe exigir que los datos de entrada estén en un formato determinado, lo que anula el objetivo. Agregar líneas nuevas a sus datos solo para formatearlo para tener nuevas líneas es desagradable. Se maneja para usted por ostream_iterator todos modos:

std::copy(buffer.begin(), buffer.end(), //    vvvv 
      std::ostream_iterator<std::string>(out_file, "\n")); 

Cualquier cosa más compleja, hacer una lambda en la impresión; no modifique sus datos de antemano.

+0

simplemente ayude al compilador a hacer RVO o mover devolviendo el nombre temporal sin nombre: 'return de.path(). String() + '\ n';' –

+0

@Gene: Lo moverá de todos modos. – GManNickG

+0

Gracias. No tenía idea de que algo como 'make_move_iterator' existiera (no he leído n3242 por completo). No creo que Boost.Filesystem sea compatible con la semántica de los movimientos, aunque creo que planean hacerlo en el futuro. – mmoran

Cuestiones relacionadas