Bug 40925

Summary: [c++0x] [DR811] std::pair<T*,U*> constructor doesn't accept (0, 0)
Product: gcc Reporter: Richard Smith <richard-gccbugzilla>
Component: libstdc++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: fang, gcc-bugs, joerg.richter
Priority: P3    
Version: 4.4.1   
Target Milestone: 4.5.0   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99957
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2009-07-31 16:14:10

Description Richard Smith 2009-07-31 15:15:18 UTC
This expression:

  std::pair<T*, U*>(0, 0)

... compiles with -std=c++98, but does not compile with -std=c++0x. We have tens, possibly hundreds, of such constructs in our codebase. Either this is a libstdc++ bug or an (I think fairly serious) issue in the changes to std::pair in the C++-0x working paper. If the types in question are known, this can be worked around by using std::make_pair<T*,U*> instead of std::pair<T*,U*>. Cases with no nice workaround include:

typedef std::map<T*, U> M;
// Later:
m.insert(M::value_type(0, x));

... and ...

std::pair<T*, U*> pair(0, 0);

The former case seems to have no workaround other than listing the types T* and U again. The latter case can be worked around with auto, but we wish to keep our code compiling with -std=c++98 too, for now, so I think we're reduced to repeating the types T* and U*.

The compilation error is:

/usr/include/c++/4.4/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = int, _U2 = int, _T1 = T*, _T2 = U*]’:
/usr/include/c++/4.4/bits/stl_pair.h:90: error: invalid conversion from ‘int’ to ‘T*’

Presumably the std::pair<T,U>::pair(T, U) constructor has been removed in favour of this more "general" one?
Comment 1 Richard Smith 2009-07-31 15:26:26 UTC
Working draft N2914, 20.3.3 says:

template <VariableType T1, VariableType T2>
struct pair {
  [...]
  requires CopyConstructible<T1> && CopyConstructible<T2> pair(const T1 &x, const T2 &y);

... and this is (modulo concept constraints) present in stl_pair.h, but I imagine that an argument of 0 doesn't select this constructor.
Comment 2 Paolo Carlini 2009-07-31 15:28:50 UTC
These issues are known, and the specifications of std::pair for C++0x are in flux. The updated specifications will be implemented in due course, when sufficiently stable vs the removal of Concepts and the parallel changes to std::map & co. Remember C++0x is an *experimental* mode, we make no guarantees.
Comment 3 Paolo Carlini 2009-07-31 16:13:54 UTC
Let's suspend the issue, but anyway, has to wait for std::pair to stabilize a bit in the Standard. To be clear, this is the original issue, which has been filed after our original implementation of a previous Draft:

  http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#811

Then came Concepts and fixed it in the Draft Standard. But now Concepts are gone and std::pair is in flux anyway for other reasons (see, e.g n2908)...
Comment 4 Paolo Carlini 2009-07-31 16:14:28 UTC
Waiting...
Comment 5 Jörg Richter 2009-09-18 13:47:01 UTC
I found Doug Gregors workaround for this pair problem:
http://gcc.gnu.org/ml/libstdc++/2008-10/msg00080.html

I wonder why it was reverted 9 days later?  I couldn't find any discussion on gcc-patches nor libstdc++.  Perhaps I have missed something.  Was this patch
not good enough? 

The reason I ask is that I want to use C++0x.  Currently I do this with "-std=gnu++0x -U__GXX_EXPERIMENTAL_CXX0X__"

I undefine __GXX_EXPERIMENTAL_CXX0X__ just because of the pair(0) problem.
But unfortunately this doesn't give me the library features of C++0x :(
Comment 6 Paolo Carlini 2009-09-18 14:10:59 UTC
(In reply to comment #5)
> I wonder why it was reverted 9 days later?  I couldn't find any discussion on
> gcc-patches nor libstdc++.  Perhaps I have missed something.

You did, it caused libstdc++/37919, as you can see in the ChangeLog. Really, let's wait at least the Santa Cruz meeting to have a definite direction on DR 811...
Comment 7 paolo@gcc.gnu.org 2009-10-29 19:26:19 UTC
Subject: Bug 40925

Author: paolo
Date: Thu Oct 29 19:26:04 2009
New Revision: 153725

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=153725
Log:
2009-10-29  Paolo Carlini  <paolo.carlini@oracle.com>

	PR libstdc++/40925
	* include/bits/stl_pair.h (pair<_T1, _T2>::pair(_U1&&, _U2&&)):
	Use enable_if to remove it from the overload set when either _U1
	is not convertible to _T1 or _U2 is not convertible to _T2.
	(pair<>::pair(_U1&&, _Arg0&&, _Args&&...)): Remove.

2009-10-29  Douglas Gregor  <doug.gregor@gmail.com>

	PR libstdc++/40925
	* testsuite/20_util/pair/40925.cc: Add.

Added:
    trunk/libstdc++-v3/testsuite/20_util/pair/40925.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/bits/stl_pair.h

Comment 8 paolo@gcc.gnu.org 2009-10-30 02:29:29 UTC
Subject: Bug 40925

Author: paolo
Date: Fri Oct 30 02:29:14 2009
New Revision: 153733

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=153733
Log:
2009-10-29  Paolo Carlini  <paolo.carlini@oracle.com>
  	    Douglas Gregor  <doug.gregor@gmail.com>

	PR libstdc++/40925 (again)
	* include/bits/stl_pair.h (pair<_T1, _T2>::pair(_U1&&, const _T2&),
	pair<_T1, _T2>::pair(const _T1&, _U2&&)): Add, to deal correctly
	with move-only types in the presence of "null pointers".
	* testsuite/20_util/pair/40925.cc: Extend.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/bits/stl_pair.h
    trunk/libstdc++-v3/testsuite/20_util/pair/40925.cc

Comment 9 Paolo Carlini 2010-02-08 11:07:06 UTC
Can be closed (of course std::is_convertible needs front-end support, but that's another story)