On 12/17/2014 02:33 AM, Richard Smith wrote:
> Creation of a std::initializer_list<T> object from a braced init list does
> not violate any of the rules in [expr.const], whether or not
> std::initializer_list<T> is a literal type, so it is still a constant
> expression.
>
>
> However, there is an open question of whether (for instance) the copy
> constructor of initializer_list<T> is usable in a constant expression.
[dcl.init.list]/3.5 seems to imply that the creation of any named
std::initializer_list<T> object, e.g. as a function parameter or a
variable, requires a constexpr copy/move constructor.
The _literal type_ property, as far as I understand it, is a separate
issue; is required for a constexpr object declaration like:
#include <initializer_list>
int main() {
constexpr std::initializer_list<int> l = {1,2,3,4};
}
Which does not compile on clang++ tip-of-trunk, but I guess that's a bug (?)
> where a library function says it's constexpr, we should
> assume that any usage of that function that could reasonably be a constant
> expression is in fact a constant expression.
This does not seem to imply that std::initializer_list<T> shall be a
literal type: It can be created "magically" via list-initialization
within a constant expression (without the restrictions of a constexpr
ctor), then I can call its constexpr member functions, and those might
even access data members of the class - as far as I understand even if
the class is not a literal type. Example:
#include <initializer_list>
constexpr auto x = *std::initializer_list{1,2,3}.begin();
int main() {}
This by the way compiles with g++4.9 but not clang++ tip-of-trunk, while
#include <initializer_list>
#include <utility>
template<typename T>
constexpr decltype(auto)
make_xvalue_init_list(std::initializer_list<T>&& rvalue)
{ return std::move(rvalue); }
constexpr auto x = *make_xvalue_init_list({1,2,3}).begin();
int main() {}
compiles with both.