Eligible special member functions and triviality

Viewed 158

Consider the following code:

#include <type_traits>

template<typename T>
concept Int = std::is_same_v<T, int>;

template<typename T>
concept Float = std::is_same_v<T, float>;

template<typename T>
struct Foo
{
    Foo() requires Int<T> = default; // #1
    Foo() requires Int<T> || Float<T> = default; // #2
};

static_assert(std::is_trivial_v<Foo<float>>);

For static assert to be satisfied, Foo<float> needs to be a trivial type, so, since it is a class type, be a trivial class. Thus, apart from being trivially copyable (which it is), it has to have an eligible default constructor (and all such constructors have to be trivial, class.prop#2), which is a special case of eligible special member function, defined by special#6:

An eligible special member function is a special member function for which:

  • the function is not deleted,
  • the associated constraints ([temp.constr]), if any, are satisfied, and
  • no special member function of the same kind is more constrained ([temp.constr.order]).

Rigorously, Foo<float> does not have an eligible default constructor, because constraints of #1 are unsatisfied and for #2 there's a more constrained default constructor (#1). Thus, Foo<float> is not a trivial class. However, the code above compiles successfully on gcc, clang and msvc (godbolt). Intuitively, it probably should, but then, it seems, the third clause of the definition above should be

  • no special member function of the same kind with satisfied associated constraints (if any) is more constrained ([temp.constr.order])

to allow #2 not to be "shadowed" by #1 (which would never be chosen during overload resolution for default constructor of Foo<float> anyway) and become eligible, making (due to being trivial and only one eligible) Foo<float> trivial.

So, is my analysis correct? If so, is this a compiler bug or the wording of the aforementioned clause is imprecise and it actually implies my version of it?

1 Answers

So, is my analysis correct?

Definitely. My intent in writing this wording in P0848 was very much that #2 is eligible - that's the one overload resolution would pick and it's not deleted, so it should be eligible.

I opened a CWG issue request which is now CWG 2595.

Related