I was exploring the ugly world of std::intializer_list
.
As far as I've understood from the standard:
§ 11.6.4:
- An object of type std::initializer_list is constructed from an initializer list as if the implementation generated and materialized (7.4) a prvalue of type “array of N const E”, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std::initializer_list object is constructed to refer to that array. [ Note: A constructor or conversion function selected for the copy shall be accessible (Clause 14) in the context of the initializer list. — end note ] [...]
So, in case the type E
is a class, I expect the copy constructor to be called.
The following class does not allow copy construction:
struct NonCopyable {
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
};
I am going to try to instantiate a std::initializer_list
with this class.
#include <vector>
void foo() {
std::vector<NonCopyable>{NonCopyable{}, NonCopyable{}};
}
With g++-8.2 -std=c++14
I get what I expect, compiler error:
error: use of deleted function 'NonCopyable::NonCopyable(const NonCopyable&)'
.
Perfect!
However, the behaviour changes with the new standard.
Indeed, g++-8.2 -std=c++17
compiles.
I thought it was because of the new requirement about copy elision
provided by the new standard, at first.
However, changing the standard library implementation (keeping c++17) the error comes back:
clang-7 -std=c++17 -stdlib=libc++
fails:
'NonCopyable' has been explicitly marked deleted here NonCopyable(const NonCopyable&) = delete;
So what am I missing?
1) Does C++17 require copy-elision in the copy construction of elements of initializer_list
?
2) Why libc++
implementation does not compile here?
Edit
Please note that, in the example g++ -std=c++17
(which compiles), if I change the default constructor as "user defined":
struct NonCopyable {
NonCopyable();
NonCopyable(const NonCopyable&) = delete;
};
the program does not compile anymore (not because of link error).