std::transform and move semantics
I'm using Boost.Filesystem to create a listing of files in a directory. I use boost::filesystem::recursive_directory_iterator
and std::copy
to put each path into a std::vector as a boost::filesystem::directory_entry
object. I wish to output to the file as std::strings though, so I did the following (\n to avoid the use of <<):
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));
However the problem with this is it creates two vectors, the original of which is immediately cleared because it is not needed. This sounds like a perfect place for move semantics, but n3242 only provides the same two overloads of transform as in C++98. Is it possible to implement move semantics with std::transform
? If it is not, would writing a custom loop be better?
I'm using GCC 4.5.2 (MinGW) on Wi开发者_JS百科ndows XP.
This looks like a job for 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;
}
A move iterator is simply an iterator which moves its dereference result. Note that the class needs to support move semantics for this to even make a difference; I don't know if Boost FS does.
Note if your goal is to output them on separate lines, you're doing it wrong. Formatted printing shouldn't require the input data be in a certain format, that defeats the purpose. Adding newlines to your data just to format it to have newlines is nasty. It's handled for you by ostream_iterator
anyway:
std::copy(buffer.begin(), buffer.end(), // vvvv
std::ostream_iterator<std::string>(out_file, "\n"));
Anything more complex, make a lambda in for printing; don't modify your data beforehand.
精彩评论