title: Which type trait would indicate that type is memcpy assignable? (tuple, pair)
body: <p>I would like to know what type introspection I can do to detect types that assignable by simply raw memory copy?</p>
  
  <p>For example, as far I understand, built-in types tuples of built-in types and tuple of such tuples, would fall in this category.
  The motivation is that I want to transport raw bytes if possible.</p>
  
  <pre><code>T t1(...); // not necessarely default constructible 
  T t2(...);
  
  t1 = t2; // should be equivalent to std::memcpy(&amp;t1, &amp;t2, sizeof(T));
  // t1 is now an (independent) copy of the value of t2, for example each can go out of scope independently
  </code></pre>
  
  <p><strong>What <code>type_trait</code> or <em>combination</em> of <code>type_traits</code> could tell at compile time if assignment can be (in principle) replaced by <code>memcpy</code>?</strong></p>
  
  <p>I tried what would work for the types I would guess should fullfil this condition and to my surprise the only one that fit the behavior is not <code>std::is_trivially_assignable</code> but <code>std::trivially_destructible</code>.
  It makes sense to some level, but I am confused why some other options do not work with the expected cases.</p>
  
  <p>I understand that there may not be a bullet proof method because one can always write a class that effectively is memcopyable, that cannot be "detected" as memcopyable, but I am looking for one that works for the simple intuitive cases. </p>
  
  <pre><code>#include&lt;type_traits&gt;
  template&lt;class T&gt; using trait = 
      std::is_trivially_destructible
  //  std::is_trivial
  //  std::is_trivially_copy_assignable
  //  std::is_trivially_copyable // // std::tuple&lt;double, double&gt; is not trivially copyable!!!
  //  std::is_trivially_default_constructible
  //  std::is_trivially_default_constructible
  //  std::is_trivially_constructible
  //  std::is_pod // std::tuple&lt;double, double&gt; is not pod!!!
  //  std::is_standard_layout
  //  std::is_aggregate
  //  std::has_unique_object_representations
      &lt;T&gt;
  ;
  
  int main(){
      static_assert((trait&lt;double&gt;{}), "");
      static_assert((trait&lt;std::tuple&lt;double, double&gt;&gt;{}), "");
      static_assert((not trait&lt;std::tuple&lt;double, std::vector&lt;double&gt;&gt;&gt;{}), "");
      static_assert((not trait&lt;std::vector&lt;double&gt;&gt;{}), "");
  }
  </code></pre>
  
  <hr>
  
  <p>Of course my conviction that tuple should be memcopyable is not based on the standard but based on common sense and practice. That is, because this is generally ok:</p>
  
  <pre><code>std::tuple&lt;double, std::tuple&lt;char, int&gt; &gt; t1 = {5.1, {'c', 8}};
  std::tuple&lt;double, std::tuple&lt;char, int&gt; &gt; t2;
  t2 = t1;
  std::tuple&lt;double, std::tuple&lt;char, int&gt; &gt; t3;
  std::memcpy(&amp;t3, &amp;t1, sizeof(t1));
  assert(t3 == t2);
  </code></pre>
  
  <hr>
  
  <p>As a proof of principle, I implemented this. <s>I added a couple of conditions related to the size to avoid some possible misleading specialization of <code>std::tuple</code></s>.</p>
  
  <pre><code>template&lt;class T&gt; 
  struct is_memcopyable 
  : std::integral_constant&lt;bool, std::is_trivially_copyable&lt;T&gt;{}&gt;{};
  
  template&lt;class T, class... Ts&gt; 
  struct is_memcopyable&lt;std::tuple&lt;T, Ts...&gt;&gt; : 
      std::integral_constant&lt;bool, 
          is_memcopyable&lt;T&gt;{} and is_memcopyable&lt;std::tuple&lt;Ts...&gt;&gt;{}
      &gt;
  {};
  
  template&lt;class T1, class T2&gt; 
  struct is_memcopyable&lt;std::pair&lt;T1, T2&gt;&gt; : 
      std::integral_constant&lt;bool, 
          is_memcopyable&lt;T1&gt;{} and is_memcopyable&lt;T2&gt;{}
      &gt;
  {};
  </code></pre>
  
  <p>This is a very limited workaround because a class like:</p>
  
  <pre><code>struct A{ std::tuple&lt;double, double&gt; t; }; 
  </code></pre>
  
  <p>will still unfortunately be reported as non trivially copyable and non memcopyable.</p>