如何优雅地捕获具有指定变量的向量元素?

1 c++ c++17

我有一个函数foo(),它返回vector具有三个元素的 a 。0我想指定三个变量来捕获索引, 1,处的元素2。显然我知道正常的代码,比如

auto vec = foo();
a = vec[0]; b = vec[1]; c = vec[2];
Run Code Online (Sandbox Code Playgroud)

但我想要一种优雅的格式,就像Python一样,如下:

auto& [a,b,c] = foo();
Run Code Online (Sandbox Code Playgroud)

有没有办法实现呢?

Jan*_*tke 5

auto [a,b,c] = foo();结构化绑定)对于类似元组的类型(例如std::tupleor )是可能std::array的,但对于std::vector. 但是,您可以使用结构化绑定语法,并进行一些小的解决方法:

template <typename T>
std::array<T, 3> first_three(const std::vector<T>& vec) {
    if (vec.size() < 3) {
        throw std::invalid_argument("vec must contain at least three elements");
    }
    return { vec[0], vec[1], vec[2] };
}

auto [a, b, c] = first_three(foo());
Run Code Online (Sandbox Code Playgroud)

话虽这么说,如果您只对前三个元素感兴趣,也许foo()应该返回一个std::array<T, 3>或一些其他类似元组的类型。也许std::vector<T>一开始就使用了错误的类型。

关于移动语义的注释

first_three仅适用于当前状态下的可复制类型。您可以添加右值重载以避免复制:

template <typename T>
std::array<T, 3> first_three(std::vector<T>&& vec) {
    if (vec.size() < 3) {
        throw std::invalid_argument("vec must contain at least three elements");
    }
    return { std::move(vec[0]), std::move(vec[1]), std::move(vec[2]) };
}
Run Code Online (Sandbox Code Playgroud)

也有一些方法可以只具有一种功能,但实现起来会很烦人。对于初学者来说,std::vector::operator[]没有右值重载,而 C++17 中没有std::forward_like,因此将元素转发出向量有点棘手。