Recently, I came across this answer which describes how to initialize a std::array
of non-default-constructible elements. I was not so surprised because that answer clearly doesn't do any default-constructing.
Instead, it is constructing a temporary std::array
using aggregate initialization, then moving (if the move constructor is available) or copying into the named variable when the function returns. So we only need either the move constructor or copy constructor to be available.
Or so I thought...
Then came this piece of code which confounded me:
struct foo {
int x;
foo(int x) : x(x) {}
foo() = delete;
foo(const foo&) = delete;
foo& operator=(const foo&) = delete;
foo(foo&&) = delete;
foo& operator=(foo&&) = delete;
};
foo make_foo(int x) {
return foo(x);
}
int main() {
foo f = make_foo(1);
foo g(make_foo(2));
}
All the five special member constructors/operators are explicitly deleted, so now I shouldn't be able to construct my object from a return value, correct?
Wrong.
To my surprise, this compiles in gcc (with C++17)!
Why does this compile? Clearly to return a foo
from the function make_foo()
, we have to construct a foo
. Which means that in the main()
function we are assigning or constructing a foo
from the returned foo
. How is that possible?!
-std=c++11
or-std=c++14
flags to observe different results. – Connecticut