Частичная специализация шаблона для: std::allocator_traits?

#c #traits #allocator #specialization

Вопрос:

Можно ли специализировать шаблон std::allocator_traits, подобный этому?

 namespace falloc_ {

  template<class Tp> class FAllocator ;

}

// partial spec for all falloc_::FAllocator<U>, std::allocator_traits

template<typename Tp> 
struct std::allocator_traits<falloc_::FAllocator<Tp> > {

 using allocator_type = falloc_::FAllocator<Tp> ;
 using value_type = typename allocator_type::value_type ;

 // ...
 // All the components I need here, I will include all the code if You need them.
 // ...

} ;


namespace falloc_ {

  template<class Tp> class FAllocator {

    public:
       using value_type = Tp ;
  
  } ;

}
 

Полный код компилируется и выполняется в спецификациях класса распределителя std 20 и распределителя, класса объектов (std::allocator_traits). В этом случае мой вопрос на самом деле касается практической правильности, независимо от того, считают ли люди, которые знают больше о стандарте, запрещена ли перегрузка аналогичных классов функций, или просто предполагают, что, поскольку (полный) код компилируемый и исполняемый и работает в соответствии с намеченным планом — могу ли я считать, что я могу его использовать?

Кроме того, я протестировал распределитель с помощью кода:

   std::vector<int, falloc_::FAllocator<int> > mv ;

  for (size_t i = 0 ; i < 5 ; i  ) {
    mv.push_back(i) ;
  }

  for (int i = 4 ; i > -1 ; i--) {
    std::cout << "mv[" << i << "]: " << mv[i] << 'n' ;
  }
 

Память была выделена и освобождена правильно, я также проверил с помощью Valgrind.
Используя Gdb, я проверил, и все функции были вызваны из

 std::allocator_traits<falloc_::FAllocator<U> > // U aka int for std::vector<int, falloc_::FAllocator<int> > 
 

Заранее благодарим Вас за любые идеи, предложения и советы.

Ответ №1:

Разрешается специализировать std::allocator_traits шаблон. См. [пространство имен.std]/2:

Если явно не запрещено, программа может добавить специализацию шаблона для любого шаблона класса стандартной библиотеки в пространство std имен при условии, что (а) добавленное объявление зависит по крайней мере от одного определенного программой типа и (б) специализация соответствует требованиям стандартной библиотеки для исходного шаблона.

Явно не запрещено специализироваться std::allocator_traits , поэтому вы можете сделать это для определенного вами типа FAllocator . Это правило применяется как к полным специализациям, так и к частичным специализациям.

Имейте в виду, что ваша специализация действительно должна соответствовать всем требованиям исходного шаблона. Стандарт уже определяет определение каждого типа элемента и поведение каждой функции-члена до такой степени, что если бы вы написали свою собственную специализацию, она в основном была бы идентична оригиналу, что противоречит цели этого. Я полагаю, вы могли бы сделать что-то вроде добавления инструкций ведения std::allocator_traits<...>::construct(...) журнала, не нарушая первоначальных требований, но проще просто поместить эти инструкции ведения журнала в сам распределитель. Если вы настаиваете на том, чтобы включить их в свою allocator_traits специализацию, вы также должны быть осторожны, чтобы не столкнуться с [dcl.constexpr]/7.

Я не вижу ни одной ситуации, в которой специализация std::allocator_traits имела бы смысл.

Комментарии:

1. Спасибо Вам за Ваш ответ. Я также хотел бы поблагодарить Вас за очень хорошую документацию, которая разъясняет эту тему и за изложение проблем. В конечном счете, я хотел бы использовать свои собственные кучи памяти или арену памяти. У меня уже есть некоторая реализация указателей смещения, и мне нужно использовать стандарт c 17/20. В стандарте 17/20 функция «std :: распределитель <…> :: конструкция» отменяется с уровня распределителя в пользу функции «конструкции» в std :: распределитель_трайтов является еще одной причиной для попытки перегрузки распределитель_трайтов,

2. Я спросил только потому, что не думал, что это сработает. Меня вообще интересует обработка памяти с несколько более низкого уровня в отношении параллельного программирования.

3. Я хочу ознакомиться с проблемами в теоретическом плане, чтобы позже иметь возможность более практично создавать код на основе распределителей, помогая другим программистам, если это кому-то будет полезно.

4.@Вакуумируйте allocator_traits<A>::construct вызовы функции A::construct . Вы должны реализовать A::construct , но использовать allocator_traits<A>::construct в общем коде.