将一个向量转化为常量向量

4

我手头拥有一些Foo向量,希望将其转换为Bar向量,且const。我能想到最好的方法是:

Bar foo2bar(const Foo& foo);

std::vector<Foo> foos = {...};

const std::vector<Bar> bars = [&foos] {
    std::vector<Bar> bars;
    bars.reserve(foos.size());
    std::transform(foos.cbegin(), foos.cend(),
                   std::back_inserter(bars),
                   foo2bar);
    return bars;
}();

我认为大多数编译器应该省略lambda的返回值,因此这应该是接近理想的。唯一的缺点可能是需要创建一个lambda,但我认为这不是太大的问题。
这种方法是否存在任何隐匿的问题?是否有更好的方法(例如更快、更干净)?可以使用C++11。
3个回答

4
您最简单的解决方案是完全放弃const要求。您仍然可以向其他作用域公开对const的引用。
如果无法实现,这种方法应该也可以。Lambda主体可能会被内联,lambda的"创建"是一个编译时过程,返回值将被移动或完全省略。实际上,您的方法非常优雅。

是的,这是我们团队的一种样式指南,尽可能地标记对象为const(有时可能有点过于迂腐,但能使代码更加安全),所以我得想办法解决。感谢您的建议! - Zizheng Tai
@ZizhengTai:没错,我在任何可能的情况下都会提倡使用“const”。但你必须知道在哪里划界。 - Lightness Races in Orbit

2

如果你真的不能接受lambda表达式的想法,那么你可以使用boost的transform_iterator

#include <vector>
#include <boost/iterator/transform_iterator.hpp>

struct Foo {};
struct Bar {};

Bar foo2bar(const Foo& f) {
    return Bar {};
}

int main()
{
    std::vector<Foo> foos = {  };

    using boost::make_transform_iterator;
    const std::vector<Bar> bars (make_transform_iterator(foos.begin(), &foo2bar),
                                 make_transform_iterator(foos.end(), &foo2bar));
}

然而,Lambda在优化后没有性能惩罚,且较不晦涩难懂,所以我建议使用Lambda。

1

或者您可以将 foo2bar() 函数移动到您的 Foo 类中作为一个 转换运算符

struct Bar {};
struct Foo
{
    // conversion opertor
    operator Bar() const
    {
        // code to create Bar bar
        return bar;
    }
};

int main()
{
    std::vector<Foo> foos = {};

    const std::vector<Bar> bars(foos.begin(), foos.end());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接