简体   繁体   中英

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?

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);
    // ...
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM