gpt4 book ai didi

c++ - 不同类型的三元运算符

转载 作者:IT老高 更新时间:2023-10-28 22:15:04 25 4
gpt4 key购买 nike

以下代码在 g++ 4.9.2 和 clang++ 3.7.0 下的行为不同。哪一个是正确的?标准中的哪些部分与此相关?谢谢。

#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++ 接受它并且clang++ 给出错误不兼容的操作数类型('Derived' 和'Base')。详情见下文。

[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' and 'Base')
const Base& b = true ? Derived() : Base();
^ ~~~~~~~~~ ~~~~~~
1 error generated.

最佳答案

我手边没有 N3936,但 N3797 §5.12 [expr.cond]/3 包含这个(强调我的):

Otherwise, if the second and third operand have different types and either has (possibly cv-qualified) class type, or if both are glvalues of the same value category and the same type except for cv-qualification, an attempt is made to convert each of those operands to the type of the other. The process for determining whether an operand expression E1 of type T1 can be converted to match an operand expression E2 of type T2 is defined as follows:

  • If E2 is an lvalue: [removed]
  • If E2 is an xvalue: [removed]
  • If E2 is a prvalue or if neither of the conversions above can be done and at least one of the operands has (possibly cv-qualified) class type:
    • if E1 and E2 have class type, and the underlying class types are the same or one is a base class of the other:
      E1 can be converted to match E2 if the class of T2 is the same type as, or a base class of, the class of T1, and the cv-qualification of T2 is the same cv-qualification as, or a greater cv-qualification than, the cv-qualification of T1. If the conversion is applied, E1 is changed to a prvalue of type T2 by copy-initializing a temporary of type T2 from E1 and using that temporary as the converted operand.

Using this process, it is determined whether the second operand can be converted to match the third operand, and whether the third operand can be converted to match the second operand. If both can be converted, or one can be converted but the conversion is ambiguous, the program is ill-formed. If neither can be converted, the operands are left unchanged and further checking is performed as described below. If exactly one conversion is possible, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section.

现在复制初始化最终的 Base来自 Derived() 的操作数,我们可以看看§13.3.1.3 [over.match.ctor]:

When objects of class type are direct-initialized (8.5), or copy-initialized from an expression of the same or a derived class type (8.5), overload resolution selects the constructor. For direct-initialization, the candidate functions are all the constructors of the class of the object being initialized. For copy-initialization, the candidate functions are all the converting constructors (12.3.1) of that class. The argument list is the expression-list or assignment-expression of the initializer.

转换构造函数在 §12.3.1 [class.conv.ctor] 中定义如下:

A constructor declared without the function-specifier explicit specifies a conversion from the types of its parameters to the type of its class. Such a constructor is called a converting constructor.

现在,如果您相信我(为了避免引用超过我对 13.3 的引用),prvalue Derived()将导致重载决议选择移动构造函数(取 Base&& ),despite being deleted ,这会导致 Clang 的错误。

总之,Clang 发出错误是正确的。由于使用已删除的函数需要诊断,这是 GCC 中的一个错误。

关于c++ - 不同类型的三元运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29381171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com