Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::initializer_list<int const> cannot be constructed from std::initializer_list<int>

My question is about the lack of conversions between std::initializer_list types where the contained type is more or less cv qualified when those conversions appear to be easily doable.

Consider the following code which is invalid:

std::initializer_list<int> x{1,2,3,4,5,6};
std::initializer_list<int const> y = x; // error! cannot convert!

Now consider std::optional and ignore the ridiculous types:

std::optional<std::vector<int>> x{std::in_place, {1,2,3,4,5}}; // OK
std::optional<std::vector<int const>> y{std::in_place, {1,2,3,4,5}}; // error!

I assume the language spec requires deducing non cv qualified U's for std::initializer_list<U> by default.

As far as I can tell, the whole point of std::optional (and std::any and std::variant) having std::initializer_list constructor overloads is to avoid specifying the exact type of the initializer list. To get the second line of the above code to compile, that's exactly what you must do.

std::initializer_list already holds a const* to it's data (in libc++ anyhow). There's no reason I can see for the above code not to work? Is this a solvable issue in the language, or am I missing something?

like image 795
xcvr Avatar asked Sep 12 '26 05:09

xcvr


1 Answers

It sounds like your question is why std::initializer_list<T const> cannot be constructed from std::initializer_list<T> despite the fact that it would be easy to implement such a conversion.

I think the answer is that you are not supposed to have std::initializer_list<T const> in the first place, given that, as you noted, std::initializer_list<T> only gives const access to its elements anyway.

It might therefore be said that there is a "cultural norm" in C++ that you are not supposed to have any constructors that require a std::initializer_list<T const> argument. None of the standard library containers do, for instance, since a cv-qualified value type is illegal anyway (except in the case of std::array, which, of course, has no user-defined constructors anyway).

If you write your own type MyContainer that supports MyContainer<T const>, then I suggest that you make it look like the following:

template <class T>
class MyContainer {
  public:
    MyContainer(std::initializer_list<std::remove_cv_t<T>> il);
    // ...
};
like image 83
Brian Bi Avatar answered Sep 14 '26 17:09

Brian Bi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!