简体   繁体   中英

Can the std::vector range constructor invoke explicit conversions?

Is the following program well-formed?

#include <vector>
struct A {
    explicit A(int) {}
};
int main() {
    std::vector<int> vi = {1, 2, 3, 4, 5};
    std::vector<A> va(vi.begin(), vi.end());
}

According to C++17 [sequence.reqmts], the requirement for

X u(i, j);

where X is a sequence container, is:

T shall be EmplaceConstructible into X from *i .

However, in the preceding paragraph it is stated that:

i and j denote iterators satisfying input iterator requirements and refer to elements implicitly convertible to value_type ,

Thus it seems to me that both requirements would need to be met: the value type of the range must be implicitly convertible to the value type of the container, and EmplaceConstructible must be satisfied (which means the allocator must be able to perform the required initialization). Since int is not implicitly convertible to A , this program should be ill-formed.

However, surprisingly, it seems to compile under GCC .

It is only a requirement for sequence containers to support the construction from iterators that satisfy the criteria of implicit convertibility.

This does not by itself disallow sequence containers to from supporting that construction from iterators that don't satisfy that criteria as far as I can tell 1 . There is explicit rule about that:

If the constructor... is called with a type InputIterator that does not qualify as an input iterator , then the constructor shall not participate in overload resolution.

It is unclear what "qualify as an input iterator" means exactly in the context. Is it informal way to express Cpp17InputIterator, or does it attempt to refer to requirements of i and j? I don't know. Whether it is allowed or not, standard doesn't have a strict requirement for detecting it:

[container.requirements.general]

The behavior of certain container member functions and deduction guides depends on whether types qualify as input iterators or allocators. The extent to which an implementation determines that a type cannot be an input iterator is unspecified, except that as a minimum integral types shall not qualify as input iterators. ...

With the interpretation that any Cpp17InputIterator "qualifies as an input iterator", the example program would not be required to be ill-formed. But it is not guaranteed to be well-formed either.

1 In such case, it might be considered a quality of implementation issue to warn when relying on it. On the other hand, this limitation to implicit conversions may be considered a defect .


PS This compiles without warnings in Clang (with libc++) and Msvc as well.

PPS This wording seems to have been added in C++11 (which is natural, as then were explicit constructors also introduced).

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