Consider std::latch
[thread.latch.class]:
namespace std {
class latch {
public:
static constexpr ptrdiff_t max() noexcept;
constexpr explicit latch(ptrdiff_t expected);
~latch();
latch(const latch&) = delete;
latch& operator=(const latch&) = delete;
void count_down(ptrdiff_t update = 1);
bool try_wait() const noexcept;
void wait() const;
void arrive_and_wait(ptrdiff_t update = 1);
private:
ptrdiff_t counter; // exposition only
};
}
Note that destructor is present. This means that this should hold:
static_assert(std::is_trivially_destructible_v<std::latch> == false);
However, it is opposite for the implementations (MSVC STL, libstdc , libc ): https://godbolt.org/z/6s8173zTc
Is this:
- Implementation freedom (implementations are correct,
is_trivially_destructible_v
may betrue
orfalse
) - Implementation defect in every implementation (implementation should have non-trivial destructor for
std::latch
) - Standard defect (Standard shouldn't have specified
std::latch
to have non-trivial destructor)
?
CodePudding user response:
This is implementation freedom. The C standard defines the class, the implementation of the class is up, well, to the implementation.
There are some classes where the standard explicitly mandates a trivial destructor. For example, if an existing class is trivially destructible then its std::optional
also must be trivially destructible. This needs to be spelled out.
Therefore, unless somewhere there is an explicit statement that the class is or is not trivially constructible, then this is up to the implementation (where possible).
Looking at gcc's header file: it doesn't merely declare, but it explicitly defines the destructor:
~latch() = default;
Based on that the compiler can work out that the whole thing is trivially destructible.