4

I wrote a function like below:

template <typename T>
std::tuple<std::vector<T>, T, T> f() {
    std::vector<T> p(1000);
    return std::make_tuple(std::move(p), 10, 10);
}

Since the return type is quite complicated, is it guaranteed that under c++11 the compiler will either apply copy elision or move semantic when it constructs the result or I have to explicitly say something like std::move(std::make_tuple(std::move(p), 10, 10))?

dyp
  • 38,334
  • 13
  • 112
  • 177
Huy Le
  • 416
  • 4
  • 6
  • Not sure, so it is not an answer: copy elision is guaranteed when not using named variables. Instead, use rvalue references like: std::make_tuple(std::vector(1000), 10, 10); so removing the variable. The compiler will perform copy elision. When using variables, it is not guaranteed, but an optimization, thus compiler dependant. – LoPiTaL Jun 26 '15 at 16:17
  • @LoPiTaL When doing `return std::make_tuple(...)`, the return value is move-constructed from the temporary. In `auto x = f();`, `x` is move-constructed from the return value. Copy elision allows the compiler to omit one of these *moves*. At no point will the `vector` be copied, regardless of optimization. – Tavian Barnes Jun 26 '15 at 16:27
  • Do you think std::move(p) is redundant? I tried something like auto x = std::make_tuple(std::move(p), 10, 10) and I discovered that it makes a copy of p (by checking the size of p). – Huy Le Jun 26 '15 at 19:21

1 Answers1

1

AFAIK copy elision is always optional. Standard just explicitly say that compiler is allowed to make such optimization, because it changes the observable behaviour, it does not mandate it. Specifically 12.8 p. 31:

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects.

Disclaimer: This is from community draft n3690, but version for c++11 has similar statement if not exactly the same.

By the way, the criteria are specified right there.

For move, however, it is guaranteed. You make a temporary object and return it (i.e. std::make_tuple returns an rvalue and you pass it forward), the arguments to the template do not change the support for move semantics.

luk32
  • 15,812
  • 38
  • 62