#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
в общем коде.