Является ли std::istream_iterator trivially copy constructible?
#include <iterator>
#include <type_traits>
static_assert(std::is_trivially_copy_constructible_v<std::istream_iterator<int>>);
Почему программа компилируется msvc, но не компилируется gcc/clang? https://godbolt.org/z/TfaeqWcMz
Согласно cppreference, std::istream_iterator<int> должен быть trivially copy constructible.
Ответы (1 шт):
Действительно, согласно стандарту, std::istream_iterator<int> должен быть trivially copy constructible.
istream_iterator(const istream_iterator& x) = default;...
Remarks: If
is_trivially_copy_constructible_v<T>istrue, then this constructor is trivial.
namespace std {
...
template<class T, class... Args> struct is_constructible;
...
template<class T, class... Args> struct is_trivially_constructible;
...
template<class T> struct is_trivially_copy_constructible;
...
template<class T, class... Args>
inline constexpr bool is_constructible_v = is_constructible<T, Args...>::value;
...
template<class T, class... Args>
inline constexpr bool is_trivially_constructible_v
= is_trivially_constructible<T, Args...>::value;
...
template<class T>
inline constexpr bool is_trivially_copy_constructible_v
= is_trivially_copy_constructible<T>::value;
...
}
[meta.unary.prop]/tab:meta.unary.prop:
| Template | Condition | Preconditions |
|---|---|---|
| ... | ... | ... |
template<class T, class... Args> |
For a function type T or for a cv void type T, is_constructible_v<T, Args...>is false, otherwise see below |
T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound. |
| ... | ... | ... |
template<class T, class... Args> |
is_constructible_v<T, Args...>is true and the variable definition for is_constructible, as defined below, is known to call no operation that is not trivial ([basic.types], [special]). |
T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound. |
| ... | ... | ... |
template<class T> |
For a referenceable type T, the same result as is_trivially_constructible_v<T, const T&>, otherwise false. |
T shall be a complete type, cv void, or an array of unknown bound. |
| ... | ... | ... |
The predicate condition for a template specialization
is_constructible<T, Args...>shall be satisfied if and only if the following variable definition would be well-formed for some invented variablet:
T t(declval<Args>()...);...
Arithmetic types ([basic.fundamental]), enumeration types, pointer types, pointer-to-member types ([basic.compound]),
std::nullptr_t, and cv-qualified versions of these types are collectively called scalar types. Scalar types, trivially copyable class types ([class.prop]), arrays of such types, and cv-qualified versions of these types are collectively called trivially copyable types. ...
Однако в реализации gcc копирующий конструктор является user-provided, что делает его нетривиальным для любого типа.
istream_iterator(const istream_iterator& __obj)
: _M_stream(__obj._M_stream), _M_value(__obj._M_value),
_M_ok(__obj._M_ok)
{ }
A copy/move constructor for class X is trivial if it is not user-provided and if:
...
clang и msvc в этом случае соответствуют стандарту. В вашем примере для clang вы не указали флаг -stdlib=libc++, поэтому по умолчанию использовалась стандартная библиотека libstdc++, что и в gcc. Сравните.
Интересно, что разработчик gcc опубликовал LWG-3600, в котором предлагает убрать требование trivially copy constructible для std::istream_iterator из стандарта, т.к. изменение реализации поломает ABI libstdc++. Пока что никаких решений по этому поводу не принято.