c++ - ternary operator of different types -


the following piece of code behaves differently under g++ 4.9.2 , clang++ 3.7.0. 1 correct? part in standard related this? thanks.

#include <iostream> using namespace std;  struct base {   base() = default;   base(const base&) = default;   base(base&&) = delete; };  struct derived : base { };  int main() {   const base& b = true ? derived() : base(); } 

g++ accepts , clang++ gives error incompatible operand types ('derived' , 'base'). see below details.

[hidden]$ g++ -v using built-in specs. collect_gcc=/usr/bin/g++ collect_lto_wrapper=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper target: x86_64-redhat-linux configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/build/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/build/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux thread model: posix gcc version 4.9.2 20150212 (red hat 4.9.2-6) (gcc)  [hidden]$ g++ -std=c++11 b.cpp  [hidden]$ clang++ -v clang version 3.7.0 (http://llvm.org/git/clang.git 6bbdbba8ec8a7730c68fee94363547dc2dc65b10) target: x86_64-unknown-linux-gnu thread model: posix found candidate gcc installation: /usr/lib/gcc/x86_64-redhat-linux/3.4.6 found candidate gcc installation: /usr/lib/gcc/x86_64-redhat-linux/4.9.2 selected gcc installation: /usr/lib/gcc/x86_64-redhat-linux/4.9.2 candidate multilib: .;@m64 candidate multilib: 32;@m32 selected multilib: .;@m64 [hidden]$ clang++ -std=c++11 b.cpp  b.cpp:14:24: error: incompatible operand types ('derived' , 'base')   const base& b = true ? derived() : base();                        ^ ~~~~~~~~~   ~~~~~~ 1 error generated. 

i don't have n3936 handy, n3797 §5.12 [expr.cond]/3 contains (emphasis mine):

otherwise, if second , third operand have different types , either has (possibly cv-qualified) class type, or if both glvalues of same value category , same type except cv-qualification, attempt made convert each of operands type of other. process determining whether operand expression e1 of type t1 can converted match operand expression e2 of type t2 defined follows:

  • if e2 lvalue: [removed]
  • if e2 xvalue: [removed]
  • if e2 prvalue or if neither of conversions above can done , @ least 1 of operands has (possibly cv-qualified) class type:
    • if e1 , e2 have class type, , underlying class types same or one base class of other:
      e1 can converted match e2 if class of t2 same type as, or base class of, class of t1, , cv-qualification of t2 same cv-qualification as, or greater cv-qualification than, cv-qualification of t1. if conversion applied, e1 changed prvalue of type t2 copy-initializing temporary of type t2 e1 , using temporary converted operand.

using process, determined whether second operand can converted match third operand, , whether third operand can converted match second operand. if both can converted, or 1 can converted conversion ambiguous, program ill-formed. if neither can converted, operands left unchanged , further checking performed described below. if 1 conversion possible, conversion applied chosen operand , converted operand used in place of original operand remainder of section.

now copy-initialize final base operand derived(), can @ §13.3.1.3 [over.match.ctor]:

when objects of class type direct-initialized (8.5), or copy-initialized expression of same or derived class type (8.5), overload resolution selects constructor. direct-initialization, candidate functions constructors of class of object being initialized. for copy-initialization, candidate functions converting constructors (12.3.1) of class. argument list expression-list or assignment-expression of initializer.

converting constructors defined follows in §12.3.1 [class.conv.ctor]:

a constructor declared without function-specifier explicit specifies conversion types of parameters type of class. such constructor called converting constructor.

now, if you'll believe me (for sake of not having quote more have of 13.3) prvalue derived() cause overload resolution choose move constructor (taking base&&), despite being deleted, causes error clang.

in conclusion, clang correct in issuing error. using deleted function requires diagnostic, bug in gcc.


Comments

Popular posts from this blog

javascript - AngularJS custom datepicker directive -

javascript - jQuery date picker - Disable dates after the selection from the first date picker -