I have a 100% working code, which uses C style #defines, but should be converted to c style (using=) because this is the style of the rest of the code.
I am not proficient in C and struggling to convert the ::value notation.
My code checks if container (like vector/set/map) and its element use the same allocator.
template <typename Cont, typename elem>
using allocIsRecursive = typename std::uses_allocator<elem, typename Cont::allocator_type>;
template <typename Cont>
using allocIsTrivial = typename std::uses_allocator<Cont, std::allocator<char>>;
// Here are 2 defines which I wrote and am struggling to convert....
#define allocShouldPropagate(Cont, elem) \
(allocIsRecursive<Cont, typename Cont::elem>::value && !allocIsTrivial<Cont>::value)
#define allocShouldPropagateMap(Map) (allocShouldPropagate(Map, key_type) || allocShouldPropagate(Map, mapped_type))
*~~~~~~~~~~~~~~~~~~~~~
More context: The code is used when inserting new element into a container via default empty constructor. If container should be propagated, an allocator aware constructor is used instead.
Example for vector:
template <typename C>
std::enable_if_t<allocShouldPropagate(C, value_type), typename C::value_type>
defaultVectorElement(C& c) {
return typename C::value_type{c.get_allocator()};
}
template <typename C>
std::enable_if_t<!allocShouldPropagate(C, value_type), typename C::value_type>
defaultVectorElement(C& c) {
return typename C::value_type{};
}
Note: std::scoped_allocator_adaptor<> does something similar to simple containers but it does not work well for complicated containers, like maps, hashtables, it has a measurable cpu penalty.
CodePudding user response:
Is this what you are looking for?
template <typename Cont, typename elem>
constexpr bool allocIsRecursive_v = std::uses_allocator<elem, typename Cont::allocator_type>::value;
template <typename Cont>
constexpr bool allocIsTrivial_v = std::uses_allocator<Cont, std::allocator<char>>::value;
template <typename Cont, typename elem>
constexpr bool allocShouldPropagate_v = allocIsRecursive_v<Cont, typename Cont::elem> && !allocIsTrivial_v<Cont>;
template <typename Map>
constexpr bool allocShouldPropagateMap_v = allocShouldPropagate_v<Map, typename Map::key_type> || allocShouldPropagate_v<Map, typename Map::value_type>;
Then in your usecase you'd change allocShouldPropagate(C, value_type)
to allocShouldPropagate_v<C, typename C::value_type>
.