Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c++17

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.

like image 574
Brian Bi Avatar asked Oct 31 '19 16:10

Brian Bi


1 Answers

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 tell1. 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.

1In 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.


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

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

like image 55
eerorika Avatar answered Nov 01 '22 23:11

eerorika