Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type trait to identify types that can be read/written in binary form

Is there a type trait (or concept) to identify those types for which the following is safe?

template <typename T>
std::enable_if_t<std::some_type_trait<T>::value> Write(std::ostream &os,const T &x)
  { os.write(reinterpret_cast<const char *>(&x),sizeof(T)); }

template <typename T>
std::enable_if_t<std::some_type_trait<T>::value> Read(std::istream &is,T &x)
  { is.read(reinterpret_cast<char *>(&x),sizeof(T)); }

I’m thinking of classes containing POD excluding pointers (but not arrays). Something like StandardLayoutTypes but without pointers. I neither want to constrain the objects to be TrivialType nor TriviallyCopyable.

Sorry if I’m inaccurate. I know very little of data representation.

like image 524
metalfox Avatar asked Nov 10 '16 11:11

metalfox


1 Answers

Given a 1st parameter of s, the read method:

Extracts characters and stores them into successive locations of the character array whose first element is pointed to by s

So your real question is: If I have initialized an object by writing a string of bytes to it's address, is it valid?

This is the concept of Value Representation. And the value representation of Trivially Copyable types is such that:

Copying the bytes occupied by the object in the storage is sufficient to produce another object with the same value

Thus you want to ensure that your object is Trivially Copyable this isn't per say a standard concept but it can be succinctly defined as:

  • Every copy constructor is Trivial or deleted
  • Every move constructor is Trivial or deleted
  • Every copy assignment operator is Trivial or deleted
  • Every move assignment operator is Trivial or deleted
  • At least one copy constructor, move constructor, copy assignment operator, or move assignment operator is non-deleted
  • Trivial non-deleted destructor

The spirit of the assertion that at least one Trivial initializer exists for the object boils down to these requirements of a Trivially Copyable type, it's non-static members, and any of it's base classes:

  1. It's given Trivial Initializer is, or behaves as, the corresponding default intializer
  2. It has no virtual methods
  3. It has no members of a volatile-qualified type

As far as the requirement of a Trivial destructor:

  • The destructor is not user-provided (meaning, it is either implicitly declared, or explicitly defined as defaulted on its first declaration)
  • The destructor is not virtual (that is, the base class destructor is not virtual)
  • All direct base classes have trivial destructors
  • All non-static data members of class type (or array of class type) have trivial destructors

Having fully defined what it means to be a Trivially Copyable type, it is impossible for a "type trait or concept" to determine whether all of these requirements are met in all cases, for example: A type that defines a Trivial Initializer with a signature that matches the default initializer may or may not be Trivially Copyable contingent on the code which initializes the type in that initializers body; For such a type, the only way to determine if it's Trivially Copyable is human inspection of the initializer. If however you are willing to tighten the requirements to what is detectable, is_trivially_copyable will guarantee that your type is Trivially Copyable.

like image 156
Jonathan Mee Avatar answered Oct 12 '22 23:10

Jonathan Mee