Skip to content

<vector>: Iterator range constructor does not enforce implicit conversion requirement #107

@miscco

Description

@miscco

Describe the bug
The standard states in the requirements for the constructors of 26.2.3 Sequence containers [sequence.reqmts] §3

In Tables 87 and 88, `X` denotes a sequence container class,
`a` denotes a value of type `X` containing elements of type `T`,
`u` denotes the name of a variable being declared,
`A` denotes `X::allocator_type` if the qualified-id `X::allocator_type` is valid and denotes a type and `allocator<T>` if it doesn’t,
`i` and `j` denote iterators satisfying input iterator requirements and refer to elements implicitly convertible to `value_type`, `[i, j)` denotes a valid range, 
`il` designates an object of type `initializer_list<value_type>`, `n` denotes a value of type `X::size_type`, `p` denotes a valid constant iterator to `a`,
`q` denotes a valid dereferenceable constant iterator to `a`,
`[q1, q2)` denotes a valid range of constant iterators in `a`,
`t`denotes an lvalue or a const rvalue of `X::value_type`, and
`rv` denotes a non-const rvalue of `X::value_type`.
`Args` denotes a template parameter pack;
`args` denotes a function parameter pack with the pattern `Args&&`.

Importantly it requires that the elements behind input iterators i and j are implicitly convertible to value_type. However, it seems that this requirement is ignored. See the following minimal example:

#include <vector>

struct foo {
    explicit foo(int b) : bar(b) {}
    int bar;
};

int main() {
    std::vector<int> input{1, 2, 3, 4, 5};
    std::vector<foo> output(input.begin(), input.end());
}

Expected behavior
Similar to the equivalent code snippet

#include <algorithm>
#include <vector>

struct foo {
    explicit foo(int b) : bar(b) {}
    int bar;
};

int main() {
    std::vector<int> input{1, 2, 3, 4, 5};
    std::vector<foo> output;
    std::copy(input.begin(), input.end(), std::back_inserter(output));
}

there should be a diagnostic about the missing conversion

Additional context
The culprit seem to be _Range_construct_or_tidy that utilizes emplace_back.

I believe that calling push_back instead would enforce the implicit conversion requirement

Metadata

Metadata

Assignees

No one assigned

    Labels

    LWG issue neededA wording defect that should be submitted to LWG as a new issueresolvedSuccessfully resolved without a commit

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions