避免 C++0x 中移动/复制的更好方法

发布于 2024-11-19 22:14:53 字数 2047 浏览 5 评论 0 原文

这个问题是从How to pass by lambda in C++0x?,但也许这是提出问题的更清晰的方式。

考虑以下代码

#include <iostream>

#define LAMBDA(x) [&] { return x; }

class A
{
public:
  A() : i(42) {};
  A(const A& a) : i(a.i) { std::cout << "Copy " << std::endl; }
  A(A&& a) : i(a.i) { std::cout << "Move " << std::endl; }
  int i;
};

template <class T>
class B
{
public:
  B(const T& x_) : x(x_) {}
  B(T&& x_) : x(std::move(x_)) {}
  template <class LAMBDA_T>
  B(LAMBDA_T&& f, decltype(f())* dummy = 0) : x(f()) {}
  T x;
};

template <class T>
auto make_b_normal(T&& x) -> B<typename std::remove_const<typename std::remove_reference<T>::type>::type>
{
  return B<typename std::remove_const<typename std::remove_reference<T>::type>::type>(std::forward<T>(x));
}

template <class LAMBDA_T>
auto make_b_macro_f(LAMBDA_T&& f) -> B<decltype(f())>
{
  return B<decltype(f())>( std::forward<LAMBDA_T>(f) );
}

#define MAKE_B_MACRO(x) make_b_macro_f(LAMBDA(x))

int main()
{
  std::cout << "Using standard function call" << std::endl;
  auto y1 = make_b_normal(make_b_normal(make_b_normal(make_b_normal(A()))));
  std::cout << "Using macro" << std::endl;
  auto y2 = MAKE_B_MACRO(MAKE_B_MACRO(MAKE_B_MACRO(MAKE_B_MACRO(A()))));
  std::cout << "End" << std::endl;
}

输出以下内容:

Using standard function call
Move 
Copy 
Copy 
Copy 
Using macro
End

很明显,宏版本以某种方式省略了所有移动/复制构造函数调用,但函数版本没有。

我认为 C++0x 中有一种语法上很好的方法可以消除所有移动和复制,而无需使用大量宏,但我无法弄清楚。

原因:

我计划使用此类没有移动或副本的代码来构建参数包,即

auto y = (_blah = "hello", _blah2 = 4);
f(y, (_blah3 = "world", _blah4 = 67));

与非参数代码相比,这些代码没有额外的移动/副本。

This question follows on from How to pass by lambda in C++0x?, but perhaps this is a clearer way to ask the question.

Consider the following code:

#include <iostream>

#define LAMBDA(x) [&] { return x; }

class A
{
public:
  A() : i(42) {};
  A(const A& a) : i(a.i) { std::cout << "Copy " << std::endl; }
  A(A&& a) : i(a.i) { std::cout << "Move " << std::endl; }
  int i;
};

template <class T>
class B
{
public:
  B(const T& x_) : x(x_) {}
  B(T&& x_) : x(std::move(x_)) {}
  template <class LAMBDA_T>
  B(LAMBDA_T&& f, decltype(f())* dummy = 0) : x(f()) {}
  T x;
};

template <class T>
auto make_b_normal(T&& x) -> B<typename std::remove_const<typename std::remove_reference<T>::type>::type>
{
  return B<typename std::remove_const<typename std::remove_reference<T>::type>::type>(std::forward<T>(x));
}

template <class LAMBDA_T>
auto make_b_macro_f(LAMBDA_T&& f) -> B<decltype(f())>
{
  return B<decltype(f())>( std::forward<LAMBDA_T>(f) );
}

#define MAKE_B_MACRO(x) make_b_macro_f(LAMBDA(x))

int main()
{
  std::cout << "Using standard function call" << std::endl;
  auto y1 = make_b_normal(make_b_normal(make_b_normal(make_b_normal(A()))));
  std::cout << "Using macro" << std::endl;
  auto y2 = MAKE_B_MACRO(MAKE_B_MACRO(MAKE_B_MACRO(MAKE_B_MACRO(A()))));
  std::cout << "End" << std::endl;
}

Which outputs the following:

Using standard function call
Move 
Copy 
Copy 
Copy 
Using macro
End

It is clear that the macro version somehow elides all move/copy constructor calls, but the function version does not.

I assume that there is a syntactically nice way of eliding all the moves and copies without lots of macros in C++0x, but I can't figure it out.

Reason:

I plan to use such code without moves or copies for building parameter packs, i.e.

auto y = (_blah = "hello", _blah2 = 4);
f(y, (_blah3 = "world", _blah4 = 67));

And have these not have no extra moves/copies compared to non parameter code.

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

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

发布评论

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

评论(1

心作怪 2024-11-26 22:14:53

您未能为 B 提供移动构造函数。提供后,我可以在 Visual Studio 2010 上进行一系列操作。它没有省略任何移动的原因是因为您创建了一个 B>>>

编译器在移动省略方面仍然非常不成熟。我希望他们以后能做得更好。

You failed to provide a move constructor for B. When that is provided, then on Visual Studio 2010 I get a bunch of moves. The reason that it doesn't ellide any of the moves is because you created a B<B<B<B<A>>>>.

Compilers are still very immature w.r.t. move ellision. I would expect them to get better at it later.

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