Firstly, references are not objects. Objects are specified in [intro.object] and references in [dcl.ref].
Subobjects are objects ([intro.object]). Therefore reference members are not subobjects and therefore a class containing only reference members (and no bases) has no subobjects (even though it has data members).
[meta.unary.prop]
The predicate condition for a template specialization has_unique_object_representations shall be satisfied if and only if:
- T is trivially copyable, and
- any two objects of type T with the same value have the same object representation, where two objects of array or non-union class type are considered to have the same value if their respective sequences of direct subobjects have the same values, ...
The sequence of subobjects is empty, and therefore equal to another empty sequence and thus all objects of type S
have the "same value"2 according to this rule.
However, objects that refer to different objects will necessarily have a different object representation. Therefore the second requirement is not1 satisified.
Therefore the object representation is not unique, and Clang is technically wrong and GCC and MSVC (which has same result as GCC) are right.
This has become1 a bit off topic if we conclude that second requirement isn't satisfied, but: Is S
trivially copyable?
static_assert(std::is_trivially_copyable_v<S>);
Passes in both Clang and GCC, but according to MSVC, S
is not trivially copyable. So, which is correct?
[class.copy.ctor]
A copy/move constructor for class X is trivial if it is not user-provided and if:
- class X has no virtual functions ([class.virtual]) and no virtual base classes ([class.mi]), and
- the constructor selected to copy/move each direct base class subobject is trivial, and
- for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial;
All of these are satisfied. Therefore S
has a trivial copy/move constructor.
[class.prop]
A trivially copyable class is a class:
- that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator ([special], [class.copy.ctor], [class.copy.assign]),
- where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and
- that has a trivial, non-deleted destructor ([class.dtor]).
All are satisfied and therefore S
is trivially copyable, and MSVC type trait is wrong to state the opposite.
1 Edit: I originally got the conclusion backwards.
2 Whether reference data members should be ignored or not when considering "value" of a class object is in my opinion debatable. This technicality of ignoring them could potentially be considered a defect in the standard.