std :: transform和move语义

mmo*_*ran 6 c++ stl c++11

我正在使用Boost.Filesystem来创建目录中的文件列表.我使用boost::filesystem::recursive_directory_iterator,并std::copy把每个路径到一个std ::向量作为一个boost::filesystem::directory_entry对象.我希望以std :: strings的形式输出到文件,所以我做了以下(\n以避免使用<<):

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));
Run Code Online (Sandbox Code Playgroud)

然而,这个问题是它创建了两个向量,其原始立即被清除,因为它不需要.这听起来像移动语义的完美位置,但是n3242只提供与C++ 98相同的两个转换重载.是否有可能实现移动语义std::transform?如果不是,那么编写自定义循环会更好吗?

我在Windows XP上使用GCC 4.5.2(MinGW).

GMa*_*ckG 9

这看起来像是一份工作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;
}
Run Code Online (Sandbox Code Playgroud)

移动迭代器只是一个移动其取消引用结果的迭代器.请注意,类需要支持移动语义才能产生差异; 我不知道Boost FS是否有.


请注意,如果您的目标是在不同的行上输出它们,那么您做错了.格式化打印不应要求输入数据采用某种格式,这样会破坏目的.为数据添加新行只是为了将其格式化为新行是令人讨厌的.ostream_iterator无论如何它都是为你处理的:

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

任何更复杂的东西,制作一个lambda用于打印; 不要事先修改您的数据.

  • 根据 [this](http://en.cppreference.com/w/cpp/algorithm/transform),“unary_op 和 binary_op 不得......修改所涉及范围的任何元素。” 我认为从输入范围移动将被视为修改其中的元素。 (3认同)