将移动语义与 std::pair 或 std::tuple 一起使用

发布于 2024-09-30 18:42:43 字数 929 浏览 10 评论 0原文

假设您想利用移动语义,但其中一个可移动类需要成为 std::pair 的一部分。目的是创建一个返回 std::pair 的函数,该函数可以被视为右值并一起转发。

但我不知道如何做到这一点,除非对 std::pair 本身进行内部更改,以使其了解移动语义。

考虑以下代码:

struct Foo
{
 Foo() { }

 Foo(Foo&& f) { }

 private:

 Foo(const Foo& f) { } // do not allow copying
};

int main() 
{
 Foo f;
 std::pair<Foo, int> res = std::make_pair(f, 10); // fails due to private copy constructor
}

问题是 std::make_pair 以及 std::pair 构造函数本身采用两个对象并尝试创建它们的内部副本。这会导致它尝试调用复制构造函数。但在我的示例中,我希望能够将新对移动res中,并确保不创建任何副本。我认为这是不可能的,除非 std::pair 本身在内部定义了以下构造函数:

pair(T1&& t1, T2&& t2) : first(std::move(t1)), second(std::move(t2))

但它没有,至少在我正在使用的编译器上没有(gcc 4.3.2 )。可能我的编译器已经过时了,实际上较新的版本将具有此移动感知构造函数。但目前我对移动语义的理解有些不稳定,所以我不确定我是否只是忽略了这里的一些东西。那么,我想要实现的目标是否可能,而无需实际重新实现 std::pair ?或者我的编译器已经过时了?

Suppose you want to take advantage of move semantics, but one of your movable classes needs to be part of an std::pair. The purpose would be to create a function that returns an std::pair that can be treated as an rvalue, and forwarded along.

But I can't see how this can be done, unless an internal change to std::pair itself is made, to make it aware of move semantics.

Consider the following code:

struct Foo
{
 Foo() { }

 Foo(Foo&& f) { }

 private:

 Foo(const Foo& f) { } // do not allow copying
};

int main() 
{
 Foo f;
 std::pair<Foo, int> res = std::make_pair(f, 10); // fails due to private copy constructor
}

The problem is that std::make_pair, as well as the std::pair constructor itself, takes two objects and tries to make internal copies of them. This causes it to try and invoke the copy constructor. But in my example, I want to be able to move the new pair into res, and ensure that no copies are made. I would think this wouldn't be possible unless std::pair itself had the following constructor defined internally:

pair(T1&& t1, T2&& t2) : first(std::move(t1)), second(std::move(t2))

But it doesn't, at least not on the compiler I'm using (gcc 4.3.2). It may be that my compiler is simply out-of-date, and newer versions in fact will have this move-aware constructor. But my understanding of move semantics is somewhat flaky at the moment, so I'm not sure if I'm simply overlooking something here. So, is what I'm trying to accomplish possible, without actually reimplementing std::pair? Or is my compiler just out of date?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若言繁花未落 2024-10-07 18:42:43

但这不是将被调用的 std::pair 构造函数。将调用 std::pair 移动构造函数,并且移动构造函数应该完全按照您的预期执行操作 (N3126 20.3.5.2/6):

template<class U, class V> pair(pair<U, V>&& p);

效果:构造函数首先使用 std::move(p.first) 进行初始化,然后使用 std::move(p.second) 进行初始化。

但是,您的示例应该失败,因为在std::make_pair(f, 10);中,f是一个左值,需要显式< code>moved,否则被复制。以下应该有效:

std::pair<Foo, int> res = std::make_pair(std::move(f), 10);

That's not the std::pair constructor that will be called, though. The std::pair move constructor will be called, and the move constructor should do exactly what you expect (N3126 20.3.5.2/6):

template<class U, class V> pair(pair<U, V>&& p);

Effects: The constructor initializes first with std::move(p.first) and second with std::move(p.second).

However, your example should fail because in std::make_pair(f, 10);, f is an lvalue and needs to be explicitly moved, otherwise it is copied. The following should work:

std::pair<Foo, int> res = std::make_pair(std::move(f), 10);
臻嫒无言 2024-10-07 18:42:43

GCC 4.3.2 不得有完整的实现。对(和元组)应具有移动构造函数:

template<class U, class V> pair(U&& x, V&& y);

效果:构造函数首先使用 std::forward(x) 进行初始化,然后使用 std::forward(y) 进行初始化。

template<class U, class V> pair(pair<U, V>&& p);

效果:构造函数首先使用 std::move(p.first) 进行初始化,然后使用 std::move(p.second) 进行初始化。

(来自 n3126 中的 [pairs.pair])

GCC 4.3.2 must not have a complete implementation. pair (and tuple) shall have move constructors:

template<class U, class V> pair(U&& x, V&& y);

Effects: The constructor initializes first with std::forward(x) and second with std::forward(y).

template<class U, class V> pair(pair<U, V>&& p);

Effects: The constructor initializes first with std::move(p.first) and second with std::move(p.second).

(From [pairs.pair] in n3126)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文