Date: Tue, 29 Apr 2025 16:27:10 +0000
Hey everyone,
I previously wrote a JSON library aiming to precisely represent JSON objects in C++. Recently, I have been contemplating how to optimize its design. In my library, there is a node type that stores an allocator, a type tag, and a union containing arithmetic types and pointers to large objects. Copying it is cheap, and its triviality depends on the allocator. It does not own the objects, behaving like a pointer, allowing arbitrary copies. Today, I realized that the String type could be stored directly as a value within the node instead of storing its pointer, when copying the String is cheap.
What types of copies are considered cheap? Undoubtedly, all trivially copyable types. However, reference-counted types like Qt’s QString and Windows’ winrt::hstring also exhibit cheap copying, even though their copy-constructors are not trivial. These types typically pointer-sized. If I can efficiently detect such types and store them directly in the node rather than allocating them on the heap and storing pointers, memory allocations could be significantly reduced.
In other words, a trait that std::string_view, winrt::hstring, and QString satisfy—but std::string does not, would allow generic code to store such types by value without wrapping them in std::unique_ptr or other wrappers. It can be implemented as follows and allows users to specialize:
template<class T>
struct is_cheap_copy_constructible : is_trivially_copy_constructible{};
template< class T >
inline constexpr bool is_cheap_copy_constructible_v =
is_cheap_copy_constructible<T>::value;
Any feedback is welcome.
Best regards,
YexuanXiao
I previously wrote a JSON library aiming to precisely represent JSON objects in C++. Recently, I have been contemplating how to optimize its design. In my library, there is a node type that stores an allocator, a type tag, and a union containing arithmetic types and pointers to large objects. Copying it is cheap, and its triviality depends on the allocator. It does not own the objects, behaving like a pointer, allowing arbitrary copies. Today, I realized that the String type could be stored directly as a value within the node instead of storing its pointer, when copying the String is cheap.
What types of copies are considered cheap? Undoubtedly, all trivially copyable types. However, reference-counted types like Qt’s QString and Windows’ winrt::hstring also exhibit cheap copying, even though their copy-constructors are not trivial. These types typically pointer-sized. If I can efficiently detect such types and store them directly in the node rather than allocating them on the heap and storing pointers, memory allocations could be significantly reduced.
In other words, a trait that std::string_view, winrt::hstring, and QString satisfy—but std::string does not, would allow generic code to store such types by value without wrapping them in std::unique_ptr or other wrappers. It can be implemented as follows and allows users to specialize:
template<class T>
struct is_cheap_copy_constructible : is_trivially_copy_constructible{};
template< class T >
inline constexpr bool is_cheap_copy_constructible_v =
is_cheap_copy_constructible<T>::value;
Any feedback is welcome.
Best regards,
YexuanXiao
Received on 2025-04-29 16:27:15