Home > front end >  How to convert c-style define of "<>::value" to "c template"
How to convert c-style define of "<>::value" to "c template"

Time:09-12

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>.

  • Related