In the following code snippet, the declaration of typedef-name CW is accepted by msvc and gcc, but rejected by clang. Godbolt link.
I think clang is probably buggy here. When determining whether decltype(ConstrainedWrapper<Wrapped>{std::declval<Wrapped>()}) is well-formed, clang seemly excessively requires the associated constraints of the default constructor to be satisfied, even if the default constructor is not selected.
#include <concepts>
#include <cstddef>
#include <utility>
struct NoDefaultCtor {
constexpr explicit NoDefaultCtor(std::nullptr_t) {}
};
template<class T>
struct Wrapper {
Wrapper() = default;
constexpr explicit Wrapper(T x) : val(std::move(x)) {}
T val{};
};
template<class T>
struct ConstrainedWrapper {
ConstrainedWrapper() requires std::default_initializable<T> = default;
constexpr explicit ConstrainedWrapper(T x) : val(std::move(x)) {}
T val{};
};
using Wrapped = Wrapper<NoDefaultCtor>;
using W [[maybe_unused]] = decltype(Wrapper<Wrapped>{std::declval<Wrapped>()});
using CW [[maybe_unused]] = decltype(ConstrainedWrapper<Wrapped>{std::declval<Wrapped>()}); // <- clang is buggy here
In the following code snippet, the declaration of typedef-name
CWis accepted by msvc and gcc, but rejected by clang. Godbolt link.I think clang is probably buggy here. When determining whether
decltype(ConstrainedWrapper<Wrapped>{std::declval<Wrapped>()})is well-formed, clang seemly excessively requires the associated constraints of the default constructor to be satisfied, even if the default constructor is not selected.