https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82840
Bug ID: 82840
Summary: call to conversion operator instead of converting
constructor in c++17 during overload resolution
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: bruno.bugs.contact at gmail dot com
Target Milestone: ---
This code compiled by gcc trunk with std=c++17 returns 1
instead of the expected 0 since D::operator C() is called instead of the
apparently better match C::C(const D&). Compiling the code with std=c++14
make this behaviour disappear and 0 is returned as expected.
gcc 7.2 also has this behaviour but 6.4 do not.
clang trunk also has this behaviour.
Rationale for why 0 should be returned instead of 1 :
(copied from the original post on stackoverflow)
Tentative reading of the standard (latest draft N4687) :
C c(d) is a direct-initialization which is not a copy elision
([dcl.init]/17.6.1). [dcl.init]/17.6.2 tells us that applicable constructors
are enumerated and that the best one is chosen by overload resolution.
[over.match.ctor] tells us that the applicable constructors are in this case
all the constructors.
In this case : C(), C(const C&) and C(const D&) (no move ctor). C() is clearly
not viable and thus is discarded from the overload set. ([over.match.viable])
Constructors have no implicit object parameter and so C(const C&) and C(const
D&) both take exactly one parameter. ([over.match.funcs]/2)
We now go to [over.match.best]. Here we find that we need to determine which of
these two implicit conversion sequences (ICS) is better. The ICS of C(const D&)
only involves a standard conversion sequence, but the ICS of C(const C&)
involves a user-defined conversion sequence.
Therefore C(const D&) should be selected instead of C(const C&).
See the discussion on stackoverflow:
https://stackoverflow.com/questions/47110853/call-to-conversion-operator-instead-of-converting-constructor-in-c17-during-ov
static int ret;
struct D;
struct C {
C() {}
C(const C&) {}
C(const D&) {}
};
struct D {
operator C() { ret = 1; return C();}
};
int main(){
D d;
C c(d);
return ret;
}
g++ -v :
Using built-in specs.
COLLECT_GCC=/home/bruno/software/gcc-svn-install/bin/g++
COLLECT_LTO_WRAPPER=/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-svn/configure
--prefix=/home/bruno/software/gcc-svn-install
Thread model: posix
gcc version 8.0.0 20171104 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-v' '-O0' '-g' '-std=c++17' '-Wall' '-Wextra' '-Wpedantic'
'-o' 'bug_DoperatorC_CconstDref_minimal' '-shared-libgcc' '-mtune=generic'
'-march=x86-64'
/home/bruno/software/gcc-svn-install/libexec/gcc/x86_64-pc-linux-gnu/8.0.0/cc1plus
-quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE
bug_DoperatorC_CconstDref_minimal.cpp -quiet -dumpbase
bug_DoperatorC_CconstDref_minimal.cpp -mtune=generic -march=x86-64 -auxbase
bug_DoperatorC_CconstDref_minimal -g -O0 -Wall -Wextra -Wpedantic -std=c++17
-version -o /tmp/cc2hfg03.s
GNU C++17 (GCC) version 8.0.0 20171104 (experimental) (x86_64-pc-linux-gnu)
compiled by GNU C version 8.0.0 20171104 (experimental), GMP version
6.1.2, MPFR version 3.1.6, MPC version 1.0.3, isl version none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory
"/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../include/c++/8.0.0
/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../include/c++/8.0.0/x86_64-pc-linux-gnu
/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/../../../../include/c++/8.0.0/backward
/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/include
/usr/local/include
/home/bruno/software/gcc-svn-install/include
/home/bruno/software/gcc-svn-install/lib/gcc/x86_64-pc-linux-gnu/8.0.0/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
GNU C++17 (GCC) version 8.0.0 20171104 (experimental) (x86_64-pc-linux-gnu)
compiled by GNU C version 8.0.0 20171104 (experimental), GMP version
6.1.2, MPFR version 3.1.6, MPC version 1.0.3, isl version none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: a6d84215658bcb7c80db361