我想知道我可以执行什么类型自省来检测可通过简单的原始内存复制分配的类型?
例如,据我了解,内置类型、内置类型的元组和此类元组的元组都属于此类。
动机是如果可能的话我想传输原始字节。
T t1(...); // not necessarely default constructible
T t2(...);
t1 = t2; // should be equivalent to std::memcpy(&t1, &t2, sizeof(T));
// t1 is now an (independent) copy of the value of t2, for example each can go out of scope independently
What type_trait
or 组合 of type_traits
可以在编译时判断赋值是否可以(原则上)替换为memcpy
?
我尝试了对我认为应该满足此条件的类型有效的方法,但令我惊讶的是,唯一适合该行为的类型不是std::is_trivially_assignable
but std::trivially_destructible
。
这在某种程度上是有道理的,但我很困惑为什么其他一些选项不适用于预期的情况。
我知道可能没有一种防弹方法,因为人们总是可以编写一个有效地可内存复制的类,该类不能被“检测”为可内存复制,但我正在寻找一种适用于简单直观情况的方法。
#include<type_traits>
template<class T> using trait =
std::is_trivially_destructible
// std::is_trivial
// std::is_trivially_copy_assignable
// std::is_trivially_copyable // // std::tuple<double, double> is not trivially copyable!!!
// std::is_trivially_default_constructible
// std::is_trivially_default_constructible
// std::is_trivially_constructible
// std::is_pod // std::tuple<double, double> is not pod!!!
// std::is_standard_layout
// std::is_aggregate
// std::has_unique_object_representations
<T>
;
int main(){
static_assert((trait<double>{}), "");
static_assert((trait<std::tuple<double, double>>{}), "");
static_assert((not trait<std::tuple<double, std::vector<double>>>{}), "");
static_assert((not trait<std::vector<double>>{}), "");
}
当然,我认为元组应该是可复制的并不是基于标准,而是基于常识和实践。也就是说,因为这通常是可以的:
std::tuple<double, std::tuple<char, int> > t1 = {5.1, {'c', 8}};
std::tuple<double, std::tuple<char, int> > t2;
t2 = t1;
std::tuple<double, std::tuple<char, int> > t3;
std::memcpy(&t3, &t1, sizeof(t1));
assert(t3 == t2);
As a proof of principle, I implemented this. I added a couple of conditions related to the size to avoid some possible misleading specialization of std::tuple
.
template<class T>
struct is_memcopyable
: std::integral_constant<bool, std::is_trivially_copyable<T>{}>{};
template<class T, class... Ts>
struct is_memcopyable<std::tuple<T, Ts...>> :
std::integral_constant<bool,
is_memcopyable<T>{} and is_memcopyable<std::tuple<Ts...>>{}
>
{};
template<class T1, class T2>
struct is_memcopyable<std::pair<T1, T2>> :
std::integral_constant<bool,
is_memcopyable<T1>{} and is_memcopyable<T2>{}
>
{};
这是一个非常有限的解决方法,因为像这样的类:
struct A{ std::tuple<double, double> t; };
不幸的是,仍然会被报告为不可平凡复制和不可内存复制。