什么特征使 uninitialized_copy(_n) 可以被 copy(_n) 取代?
What trait makes uninitialized_copy(_n) sustituable by copy(_n)?
我正在尝试理解类型属性和支持的操作的含义,https://en.cppreference.com/w/cpp/types。
我有一个库,它实现了类似于 std::copy_n
的低级功能,当然我也必须实现 uninitialized_copy
,但是对于许多类型,它们是在某种意义上微不足道,我不想重复代码并将一个委托给另一个。
什么 属性 使得 uninitialized_copy(_n)
在语义上可以被 copy(_n)
替代?
我的猜测是 std::is_trivially_default_constructible<T>::value
,但我不确定。
理由是,如果某些东西是微不足道的默认可构造的,我可以跳过赋值前的初始化。
(最初我以为它可能是std::is_trivially_assignable<TSource, T>::value
)
当然我可以稳妥地要求std::is_trivial<T>::value
,但我想更有针对性。
我知道这些特征可能有马基雅维利或误导性的定义,但假设我想相信它们。
示例代码:
template<class... As, class... Bs>
auto uninitialized_copy_n(
my_iterator<As...> first, Size count,
my_iterator<Bs...> d_first
)-> my_iterator<Bs...> {
using T1 = typename my_iterator<As...>::value_type;
using T2 = typename my_iterator<Bs...>::value_type;
if constexpr(std::is_trivially_constructible<T2>::value){
return copy_n(first, count, d_first);
}
... another implementation or abort
}
要用copy
替换uninitialized_copy
,这两个动作必须等价:
uninitialized_copy
:从Source
类型的对象构造一个Destination
类型的新对象
copy
:假设存在一个 Destination
类型的对象,并从 Source
类型的对象分配给它
必须对类型提出足够的要求,以便目标对象存在并且构造和赋值给出相同的值。
is_trivially_default_constructible
既不需要也不足以假设对象存在于内存位置。相反,目标类型必须是 implicit lifetime type。这不是递归条件,所以我们必须要求类型是隐式生命周期类型,并且递归地所有成员或子对象都是隐式生命周期类型。
例如,具有普通默认构造函数和普通析构函数的标量或 类 将起作用。
其次,我们需要构造和赋值来给出相同的结果。如果这些操作不是微不足道的,这是不可能的。但在 C++ 中,对象的值只能通过此类操作才能保证不变,这些操作适用于平凡可复制的类型,将值与表示相关联。因此,我们可能希望目的地可以轻松复制。
这给了我们:
std::is_trivially_default_constructible_v<Destination>
std::is_trivially_destructible_v<Destination>
std::is_trivially_constructible_v<Destination, const Source&>
std::is_trivially_assignable_v<Destination&, const Source&>
std::is_trivially_copyable_v<Destination>
这简化为:
std::is_trivial_v<Destination>
std::is_trivially_constructible_v<Destination, const Source&>
std::is_trivially_assignable_v<Destination&, const Source&>
注意libstdc++ requires both types to be trivial and the Destination assignable and constructible from the Source。评论引用了范围算法的一个稍微不同的条件。
libstdc++ 要求存在明显差异。参见 this example。 value
应该是 1
(来自构造)但正在填充 2
(来自分配)。我找不到任何授予实现方式不同的许可。
libstdc++ 逻辑是最近 found to be buggy 并且可能仍然是。
我正在尝试理解类型属性和支持的操作的含义,https://en.cppreference.com/w/cpp/types。
我有一个库,它实现了类似于 std::copy_n
的低级功能,当然我也必须实现 uninitialized_copy
,但是对于许多类型,它们是在某种意义上微不足道,我不想重复代码并将一个委托给另一个。
什么 属性 使得 uninitialized_copy(_n)
在语义上可以被 copy(_n)
替代?
我的猜测是 std::is_trivially_default_constructible<T>::value
,但我不确定。
理由是,如果某些东西是微不足道的默认可构造的,我可以跳过赋值前的初始化。
(最初我以为它可能是std::is_trivially_assignable<TSource, T>::value
)
当然我可以稳妥地要求std::is_trivial<T>::value
,但我想更有针对性。
我知道这些特征可能有马基雅维利或误导性的定义,但假设我想相信它们。
示例代码:
template<class... As, class... Bs>
auto uninitialized_copy_n(
my_iterator<As...> first, Size count,
my_iterator<Bs...> d_first
)-> my_iterator<Bs...> {
using T1 = typename my_iterator<As...>::value_type;
using T2 = typename my_iterator<Bs...>::value_type;
if constexpr(std::is_trivially_constructible<T2>::value){
return copy_n(first, count, d_first);
}
... another implementation or abort
}
要用copy
替换uninitialized_copy
,这两个动作必须等价:
uninitialized_copy
:从Source
类型的对象构造一个copy
:假设存在一个Destination
类型的对象,并从Source
类型的对象分配给它
Destination
类型的新对象
必须对类型提出足够的要求,以便目标对象存在并且构造和赋值给出相同的值。
is_trivially_default_constructible
既不需要也不足以假设对象存在于内存位置。相反,目标类型必须是 implicit lifetime type。这不是递归条件,所以我们必须要求类型是隐式生命周期类型,并且递归地所有成员或子对象都是隐式生命周期类型。
例如,具有普通默认构造函数和普通析构函数的标量或 类 将起作用。
其次,我们需要构造和赋值来给出相同的结果。如果这些操作不是微不足道的,这是不可能的。但在 C++ 中,对象的值只能通过此类操作才能保证不变,这些操作适用于平凡可复制的类型,将值与表示相关联。因此,我们可能希望目的地可以轻松复制。
这给了我们:
std::is_trivially_default_constructible_v<Destination>
std::is_trivially_destructible_v<Destination>
std::is_trivially_constructible_v<Destination, const Source&>
std::is_trivially_assignable_v<Destination&, const Source&>
std::is_trivially_copyable_v<Destination>
这简化为:
std::is_trivial_v<Destination>
std::is_trivially_constructible_v<Destination, const Source&>
std::is_trivially_assignable_v<Destination&, const Source&>
注意libstdc++ requires both types to be trivial and the Destination assignable and constructible from the Source。评论引用了范围算法的一个稍微不同的条件。
libstdc++ 要求存在明显差异。参见 this example。 value
应该是 1
(来自构造)但正在填充 2
(来自分配)。我找不到任何授予实现方式不同的许可。
libstdc++ 逻辑是最近 found to be buggy 并且可能仍然是。