Bug 79141 - [6/7 Regression] std::pair<int,int> p = {}; fails to compile due to ambiguous overload
Summary: [6/7 Regression] std::pair<int,int> p = {}; fails to compile due to ambiguous...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 6.3.1
: P2 normal
Target Milestone: 6.4
Assignee: Ville Voutilainen
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2017-01-18 22:16 UTC by Abdó Roig-Maranges
Modified: 2017-04-03 21:21 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work: 5.3.0, 6.2.0
Known to fail: 6.3.0, 7.0
Last reconfirmed: 2017-02-01 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Abdó Roig-Maranges 2017-01-18 22:16:42 UTC
The following program did compile with gcc's standard library 6.2 but no longer compiles on 6.3.1, reporting an error on ambiguous overload of the assignment operator (std::pair vs initializer_list). The problem looks related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77537

#include <utility>

int main() {
    std::pair<int,int> p;
    p = {};
}

It produces the following error:

$ gcc -std=c++14 gcc-bug.cpp 
gcc-bug.cpp: In function ‘int main()’:
gcc-bug.cpp:9:10: error: ambiguous overload for ‘operator=’ (operand types are ‘std::pair<int, int>’ and ‘<brace-enclosed initializer list>’)
     p = {};
          ^
In file included from /usr/include/c++/6.3.1/bits/stl_algobase.h:64:0,
                 from /usr/include/c++/6.3.1/bits/char_traits.h:39,
                 from /usr/include/c++/6.3.1/ios:40,
                 from /usr/include/c++/6.3.1/ostream:38,
                 from /usr/include/c++/6.3.1/iostream:39,
                 from gcc-bug.cpp:4:
/usr/include/c++/6.3.1/bits/stl_pair.h:359:7: note: candidate: std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(typename std::conditional<std::__and_<std::is_copy_assignable<_Tp>, std::is_copy_assignable<_T2> >::value, const std::pair<_T1, _T2>&, const std::__nonesuch&>::type) [with _T1 = int; _T2 = int; typename std::conditional<std::__and_<std::is_copy_assignable<_Tp>, std::is_copy_assignable<_T2> >::value, const std::pair<_T1, _T2>&, const std::__nonesuch&>::type = const std::pair<int, int>&]
       operator=(typename conditional<
       ^~~~~~~~
/usr/include/c++/6.3.1/bits/stl_pair.h:370:7: note: candidate: std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(typename std::conditional<std::__not_<std::__and_<std::is_copy_assignable<_Tp>, std::is_copy_assignable<_T2> > >::value, const std::pair<_T1, _T2>&, const std::__nonesuch&>::type) [with _T1 = int; _T2 = int; typename std::conditional<std::__not_<std::__and_<std::is_copy_assignable<_Tp>, std::is_copy_assignable<_T2> > >::value, const std::pair<_T1, _T2>&, const std::__nonesuch&>::type = const std::__nonesuch&] <deleted>
       operator=(typename conditional<
       ^~~~~~~~
/usr/include/c++/6.3.1/bits/stl_pair.h:376:7: note: candidate: std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(typename std::conditional<std::__and_<std::is_move_assignable<_Tp>, std::is_move_assignable<_T2> >::value, std::pair<_T1, _T2>&&, std::__nonesuch&&>::type) [with _T1 = int; _T2 = int; typename std::conditional<std::__and_<std::is_move_assignable<_Tp>, std::is_move_assignable<_T2> >::value, std::pair<_T1, _T2>&&, std::__nonesuch&&>::type = std::pair<int, int>&&]
       operator=(typename conditional<
       ^~~~~~~~
Comment 1 Richard Biener 2017-02-01 11:39:29 UTC
Confirmed.
Comment 2 Ville Voutilainen 2017-04-01 23:49:51 UTC
Mine, patch available: https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00034.html
Comment 3 ville 2017-04-03 16:31:29 UTC
Author: ville
Date: Mon Apr  3 16:30:58 2017
New Revision: 246653

URL: https://gcc.gnu.org/viewcvs?rev=246653&root=gcc&view=rev
Log:
PR libstdc++/79141
* include/bits/stl_pair.h (__nonesuch_no_braces): New.
(operator=(typename conditional<
__and_<is_copy_assignable<_T1>,
is_copy_assignable<_T2>>::value,
const pair&, const __nonesuch&>::type)): Change __nonesuch
to __nonesuch_no_braces.
(operator=(typename conditional<
__not_<__and_<is_copy_assignable<_T1>,
is_copy_assignable<_T2>>>::value,
const pair&, const __nonesuch&>::type)): Likewise.
(operator=(typename conditional<
__and_<is_move_assignable<_T1>,
is_move_assignable<_T2>>::value,
pair&&, __nonesuch&&>::type)): Likewise.
* testsuite/20_util/pair/79141.cc: New.

Added:
    trunk/libstdc++-v3/testsuite/20_util/pair/79141.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/bits/stl_pair.h
Comment 4 Ville Voutilainen 2017-04-03 16:32:06 UTC
Fixed on trunk so far, backporting...
Comment 5 ville 2017-04-03 21:20:56 UTC
Author: ville
Date: Mon Apr  3 21:20:23 2017
New Revision: 246663

URL: https://gcc.gnu.org/viewcvs?rev=246663&root=gcc&view=rev
Log:
PR libstdc++/79141

Backport from mainline
2017-04-03  Ville Voutilainen  <ville.voutilainen@gmail.com>

	PR libstdc++/79141
	* include/bits/stl_pair.h (__nonesuch_no_braces): New.
	(operator=(typename conditional<
	__and_<is_copy_assignable<_T1>,
	is_copy_assignable<_T2>>::value,
	const pair&, const __nonesuch&>::type)): Change __nonesuch
	to __nonesuch_no_braces.
	(operator=(typename conditional<
	__not_<__and_<is_copy_assignable<_T1>,
	is_copy_assignable<_T2>>>::value,
	const pair&, const __nonesuch&>::type)): Likewise.
	(operator=(typename conditional<
	__and_<is_move_assignable<_T1>,
	is_move_assignable<_T2>>::value,
	pair&&, __nonesuch&&>::type)): Likewise.
	* testsuite/20_util/pair/79141.cc: New.

Added:
    branches/gcc-6-branch/libstdc++-v3/testsuite/20_util/pair/79141.cc
Modified:
    branches/gcc-6-branch/libstdc++-v3/ChangeLog
    branches/gcc-6-branch/libstdc++-v3/include/bits/stl_pair.h
Comment 6 Ville Voutilainen 2017-04-03 21:21:19 UTC
Fixed.