这个回答引出了下面的问题。
假设我们有一个简单的
struct S {
int& i;
}
在内部(至少在GCC和Clang中)s
只包含一个指向int
的指针,并且
static_assert(sizeof(int*) == 8);
static_assert(sizeof(S) == 8);
s
是否具有唯一的对象表示形式? GCC和Clang不同意*:
static_assert( std::has_unique_object_representations_v<int*>);
static_assert(!std::has_unique_object_representations_v<S>); // GCC
static_assert( std::has_unique_object_representations_v<S>); // Clang
哪个编译器在这里,为什么?
*idclev 463035818注意到GCC和Clang之间的分歧。
请注意,Clang明确地根据Richard Smith的评论选择他们的方法,即使知道GCC拒绝了(在OP上下文中)std::has_unique_object_representations_v
,并指出GCC的这种行为是可能的bug[强调我的]:
erichkeane引用不能简单地复制,因此它们将防止结构具有唯一的对象表示。
在我看来这是错误的行为。 如果两个结构具有绑定到相同对象的引用,那么它们具有相同的对象表示形式,因此结构确实具有唯一的对象表示形式。
埃里奇基恩我不是这么想的。。。 我将注意到GCC拒绝在其实现中引用,但这可能是他们方面的一个bug。
rsmith[...] 所以我认为引用和指针一样,当被认为是类类型的对象的成员时,应该始终被认为具有唯一的对象表示。 (但是__has_unique_object_representations(T&;)
仍然应该返回false
,因为T&;
不是一个简单的可复制类型,即使包含T&;
的类可能是。)
正如@idclev 463035818所指出的,Clang和GCC都同意S
是简单可复制的,这意味着他们的分歧在于两个具有相同值的(简单可复制的)类型S
的对象是否具有相同的对象表示; @Eerorika的答复通过参考有关标准段落表明,海湾合作委员会驳回这项索赔是错误的。
首先,引用不是对象。 对象在[intro.object]中指定,引用在[dcl.ref]中指定。
子对象是对象([Intro.Object])。 因此,引用成员不是子对象,因此只包含引用成员(没有基)的类没有子对象(即使它有数据成员)。
[meta.unary.prop]
当且仅当:
子对象的序列是空的,因此等于另一个空序列,因此满足第二个要求。
s
是否可以简单地复制?
static_assert(std::is_trivially_copyable_v<S>);
在Clang和GCC中传递。 因此,GCC是错误的,因为这两个要求都得到了满足,因此s
必须具有唯一的对象表示。
另一件奇怪的事情是,根据MSVC的说法,s
是不可复制的。 因此,尽管它同意GCC关于缺乏唯一表示的观点,但根据has_unique_object_representations
的规则,它是一致和正确的。 那么,关于琐碎的可复制性,哪一个是正确的呢?
[class.copy.ctor]
如果类X的复制/移动构造函数不是用户提供的,并且如果:
这些都是满意的。 因此,S
有一个简单的复制/移动构造函数。
[class.prop]
简单可复制的类是这样的类:
所有这些都是满意的,因此s
是微不足道的可复制的,而MSVC是错误的。
s
是可复制的,因为它没有类类型的成员,也没有用户声明的成员函数。 这一点没有争议; 当idclev 463035818 poitns out时,两个编译器都同意std::is_trivially_copyable_v
==true
因此问题被简化为两个相同的S对象是否按位相同。 由于两个实现都选择将引用表示为指针(一个有效的选择),std::HAS_UNIQUE_OBJECT_REPresentations_V
必须匹配std::HAS_UNIQUE_OBJECT_REPresentations_V
。 因此,海合会错了。