Почему clang не может ограничить конструкцию кортежа явным? - PullRequest
1 голос
/ 01 июня 2019

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 ++ даже не задумывался об этом.Правильно ли я понимаю, что это ошибка?

...