This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.

### 767. Forwarding and backward compatibility

Section: 22 [containers] Status: Resolved Submitter: Sylvain Pion Opened: 2007-12-28 Last modified: 2016-01-28

Priority: Not Prioritized

View other active issues in [containers].

View all other issues in [containers].

View all issues with Resolved status.

Discussion:

Playing with g++'s C++0X mode, I noticed that the following code, which used to compile:

>     #include <vector>

>     int main()
>     {
>         std::vector<char *> v;
>         v.push_back(0);
>     }

now fails with the following error message:

> .../include/c++/4.3.0/ext/new_allocator.h: In member function 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, _Args&& ...) [with _Args = int, _Tp = char*]': .../include/c++/4.3.0/bits/stl_vector.h:707: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(_Args&& ...) [with _Args = int, _Tp = char*, _Alloc = std::allocator<char*>]' test.cpp:6: instantiated from here .../include/c++/4.3.0/ext/new_allocator.h:114: error: invalid conversion from 'int' to 'char*'

As far as I know, g++ follows the current draft here.

Does the committee really intend to break compatibility for such cases?

[ Sylvain adds: ]

> I just noticed that `std::pair` has the same issue. The following now fails with GCC's -std=c++0x mode:

> >     #include <utility>

> >     int main()
> >     {
> >        std::pair<char *, char *> p (0,0);
> >     }

> I have not made any general audit for such problems elsewhere.

[ Related to 756 ]

[ Bellevue: ]

> Motivation is to handle the old-style int-zero-valued `NULL` pointers. Problem: this solution requires concepts in some cases, which some users will be slow to adopt. Some discussion of alternatives involving prohibiting variadic forms and additional library-implementation complexity.

> Discussion of "perfect world" solutions, the only such solution put forward being to retroactively prohibit use of the integer zero for a `NULL` pointer. This approach was deemed unacceptable given the large bodies of pre-existing code that do use integer zero for a `NULL` pointer.

> Another approach is to change the member names. Yet another approach is to forbid the extension in absence of concepts.

> Resolution: These issues (756, 767, 760, 763) will be subsumed into a paper to be produced by Alan Talbot in time for review at the 2008 meeting in France. Once this paper is produced, these issues will be moved to NAD Resolved.

Proposed resolution:

Add the following rows to Table 90 "Optional sequence container operations", 22.2.3 [sequence.reqmts]:

> expression | return type | assertion/note pre-/post-condition | container
> --- | --- | --- | ---
> `a.push_front(t)` | `void` | `a.insert(a.begin(), t)` Requires: `T` shall be `CopyConstructible`. | `list, deque`
> `a.push_front(rv)` | `void` | `a.insert(a.begin(), rv)` Requires: `T` shall be `MoveConstructible`. | `list, deque`
> `a.push_back(t)` | `void` | `a.insert(a.end(), t)` Requires: `T` shall be `CopyConstructible`. | `list, deque, vector, basic_string`
> `a.push_back(rv)` | `void` | `a.insert(a.end(), rv)` Requires: `T` shall be `MoveConstructible`. | `list, deque, vector, basic_string`

Change the synopsis in 22.3.8 [deque]:

>     void push_front(const T& x);
>     void push_front(T&& x);
>     void push_back(const T& x);
>     void push_back(T&& x);
>     template <class... Args> requires Constructible<T, Args&&...> void push_front(Args&&... args);
>     template <class... Args> requires Constructible<T, Args&&...> void push_back(Args&&... args);

Change 22.3.8.4 [deque.modifiers]:

>     void push_front(const T& x);
>     void push_front(T&& x);
>     void push_back(const T& x);
>     void push_back(T&& x);
>     template <class... Args> requires Constructible<T, Args&&...> void push_front(Args&&... args);
>     template <class... Args> requires Constructible<T, Args&&...> void push_back(Args&&... args);

Change the synopsis in 22.3.10 [list]:

>     void push_front(const T& x);
>     void push_front(T&& x);
>     void push_back(const T& x);
>     void push_back(T&& x);
>     template <class... Args> requires Constructible<T, Args&&...> void push_front(Args&&... args);
>     template <class... Args> requires Constructible<T, Args&&...> void push_back(Args&&... args);

Change 22.3.10.4 [list.modifiers]:

>     void push_front(const T& x);
>     void push_front(T&& x);
>     void push_back(const T& x);
>     void push_back(T&& x);
>     template <class... Args> requires Constructible<T, Args&&...> void push_front(Args&&... args);
>     template <class... Args> requires Constructible<T, Args&&...> void push_back(Args&&... args);

Change the synopsis in 22.3.11 [vector]:

>     void push_back(const T& x);
>     void push_back(T&& x);
>     template <class... Args> requires Constructible<T, Args&&...> void push_back(Args&&... args);

Change 22.3.11.5 [vector.modifiers]:

>     void push_back(const T& x);
>     void push_back(T&& x);
>     template <class... Args> requires Constructible<T, Args&&...> void push_back(Args&&... args);

Rationale:

Addressed by N2680 Proposed Wording for Placement Insert (Revision 1).

If there is still an issue with pair, Howard should submit another issue.