1

Per [tuple.cnstr]/6:

EXPLICIT constexpr tuple();

Effects: Value-initializes each element.

Remarks: This constructor shall not participate in overload resolution unless is_­default_­constructible_­v<Ti> is true for all i. [ Note: This behavior can be implemented by a constructor template with default template arguments. — end note ] The constructor is explicit if and only if Ti is not implicitly default-constructible for at least one i. [ Note: This behavior can be implemented with a trait that checks whether a const Ti& can be initialized with {}. — end note ]

Therefore, the following code

#include <tuple>

struct A {
  explicit A() = default;
};

int main()
{
  [[maybe_unused]] std::tuple<A> x = {};
}

is ill-formed because the default constructor of std::tuple<A> is explicit. GCC 9.1.0 correctly raises an error. However, it compiles fine on Clang 8.0.0.

Here's the relevant code from libc++:

template <class ..._Args>
static constexpr bool __enable_default() {
    return __all<is_default_constructible<_Args>::value...>::value;
}

And the constructor:

template <bool _Dummy = true, class = typename enable_if<
    _CheckArgsConstructor<_Dummy>::template __enable_default<_Tp...>()
>::type>
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR tuple()
    _NOEXCEPT_(__all<is_nothrow_default_constructible<_Tp>::value...>::value) {}

It seems that libc++ didn't even think of implementing this. Is my understanding correct that this is a bug?

L. F.
  • 19,445
  • 8
  • 48
  • 82

0 Answers0