Per [tuple.cnstr] / 6 :
EXPLICIT constexpr tuple();
Эффекты: Значение инициализирует каждый элемент.
Примечания: Этот конструктор не долженучаствовать в разрешении перегрузки, если is_default_constructible_v<Ti>
не верно для всех i.[ Примечание: Это поведение может быть реализовано шаблоном конструктора с аргументами шаблона по умолчанию.- конец примечания ] Конструктор является явным тогда и только тогда, когда T<sub><i>i</i></sub>
неявно не конструируется по умолчанию хотя бы для одного i . [ Примечание: Это поведение может быть реализовано с помощью признака, который проверяет, можно ли инициализировать const
T<sub><i>i</i></sub>&
с помощью {}
.- примечание конца ]
Следовательно, следующий код
#include <tuple>
struct A {
explicit A() = default;
};
int main()
{
[[maybe_unused]] std::tuple<A> x = {};
}
некорректен, так как конструктор по умолчанию std::tuple<A>
является явным. GCC 9.1.0 правильно выдает ошибку.Тем не менее, он прекрасно компилируется на Clang 8.0.0 .
Вот соответствующий код из libc ++ :
template <class ..._Args>
static constexpr bool __enable_default() {
return __all<is_default_constructible<_Args>::value...>::value;
}
И Конструктор :
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) {}
Кажется, что libc ++ даже не задумывался об этом.Правильно ли я понимаю, что это ошибка?