up cast and copy elision question

13 views
Skip to first unread message

Sky Malice

unread,
May 3, 2017, 11:36:33 AM5/3/17
to cxx
Hey folks, I recently hit a compile error on ios/android for code that looked like

class A {};
class B : public A {};

// Fails to compile on ios and android (ios-device-xcode-clang, ios-simulator-xcode-clang, linux_android_rel_ng, android_n5x_swarming_rel, android_compile_dbg, android_arm64_dbg_recipie)
std::unique_ptr<A> Foo() {
  auto b = base::MakeUnique<B>();
  <do something that requires having a B object>
  return b;
}

My question is, what do you think is a better work around?

> return std::move(b);

or

> return base::WrapUnique<A>(b.release());

In the past I've seen compiler errors when I return std::move(local_variable) because it's blocking copy elision, but I don't understand copy elision well enough to know if it's allowed at all in this scenario. But the latter seems kind of clunky, I guess you could view it as showing explicit intent instead.

Any opinions?

Nico Weber

unread,
May 3, 2017, 11:48:04 AM5/3/17
to Sky Malice, cxx
I think we usually do `std::move(b);`. The move isn't needed in C++14 and clang allows that as an extension in C++11 mode. Newer gccs do too, but only as of 5.1. If your function were to return a std::unique_ptr<A>, having the std::move() would indeed trigger a -Wpessimizing-move warning since the move does prevent copy elision and isn't needed, but since your function returns a std::unique_ptr<B> the std::move call is needed (it still prevents copy elision, but there's no way around that in C++11) and so the warning shouldn't be emitted.

Nico


ps:

thakis@thakis:~/src/chrome/src$ cat test.cc
#include <memory>
class A {};
class B : public A {};
std::unique_ptr<A> f() {
  std::unique_ptr<B> b(new B);
  return b;
}
thakis@thakis:~/src/chrome/src$ third_party/llvm-build/Release+Asserts/bin/clang -c test.cc -std=c++11
thakis@thakis:~/src/chrome/src$ gcc -c test.cc -std=c++11
test.cc: In function ‘std::unique_ptr<A> f()’:
test.cc:6:10: error: cannot bind ‘std::unique_ptr<B>’ lvalue to ‘std::unique_ptr<B>&&’
   return b;
          ^
thakis@thakis:~/src/chrome/src$ cat test.cc
#include <memory>
class A {};
class B : public A {};
std::unique_ptr<A> f() {
  std::unique_ptr<B> b(new B);
  return std::move(b);
}
thakis@thakis:~/src/chrome/src$ third_party/llvm-build/Release+Asserts/bin/clang -c test.cc -std=c++11
thakis@thakis:~/src/chrome/src$ gcc -c test.cc -std=c++11
thakis@thakis:~/src/chrome/src$ third_party/llvm-build/Release+Asserts/bin/clang -c test.cc -std=c++11 -Wall
thakis@thakis:~/src/chrome/src$ third_party/llvm-build/Release+Asserts/bin/clang -c test.cc -std=c++14 -Wall

Arguably, -Wpessimizing-move should fire on this with -std=c++14.

thakis@thakis:~/src/chrome/src$ cat test.cc
#include <memory>
class A {};
class B : public A {};
std::unique_ptr<B> f() {
  std::unique_ptr<B> b(new B);
  return std::move(b);
}
thakis@thakis:~/src/chrome/src$ third_party/llvm-build/Release+Asserts/bin/clang -c test.cc -std=c++11 -Wall
test.cc:6:10: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move]
  return std::move(b);
         ^


--
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To post to this group, send email to c...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAGLE5TfyDGdyrmvDbKF2x9V82G5CmOchaS%2BZTNSKi-Rs6WE%3DDQ%40mail.gmail.com.

Sky Malice

unread,
May 3, 2017, 12:01:14 PM5/3/17
to Nico Weber, cxx
Thanks for the quick, detailed, and clear response! Really appreciate it, Nico.

Reply all
Reply to author
Forward
0 new messages