Search code examples
c++overloadingrvalueambiguous

Ambiguous/rvalue arguments cause compiler to choose incorrect overload


I have a home grown template class called Vec which is a pale shadow of: std::vector<T>

To avoid re-inventing the wheel the header overloads for assign are copied from: std::vector::assign

enter image description here

..so

enter image description here

As part of testing Str class, ..test code is also run against std::vector<T> to ensure equivalent output...

If std::vector<T> is used then compiler will choose the correct overload:

enter image description here

However, when Vec<T> is used then compiler insists on choosing the incorrect overload:

enter image description here

There is an obvious work around via casting the args to lvalues prior to use:

enter image description here

Question: Given that both Vec<T> and std::vector<T> use identical header overloads for their respective assign ...how is std::vector<T> able to implement rvalues arg without confusing the compiler?


Solution

  • [sequence.reqmts]/14 For every sequence container defined in this Clause and in Clause 21:

    (14.2) — If the member functions of the forms:

    template <class InputIterator> // such as insert()
    rt fx1(const_iterator p, InputIterator first, InputIterator last);
    template <class InputIterator> // such as append(), assign()
    rt fx2(InputIterator first, InputIterator last);
    template <class InputIterator> // such as replace()
    rt fx3(const_iterator i1, const_iterator i2, InputIterator first, InputIterator last);
    

    are called with a type InputIterator that does not qualify as an input iterator, then these functions shall not participate in overload resolution.

    This is typically implemented with a touch of SFINAE. You can check the headers of your favorite standard library implementation for details.