Как создать универсальную функцию вставки для пользовательского контейнера с функтором
На данный момент, я не беспокоюсь о том, что это правильное решение для моей проблемы (на самом деле, это не так), но я попал в эту проблему, и я не мог ее решить, поэтому она преследует меня, и я не могу отпустить.
У меня есть универсальный контейнер для типов POD. Этот контейнер может избежать копирования, не инициализируя память и не вызывая никаких конструкторов или деструкторов по соображениям производительности, в обмен на то, чтобы заставить пользователя нести за это ответственность (что не является большой проблемой, связанной с модулями и нашим вариантом использования).
Это очень простая демонстрация того, как это использовать.
template <typename Pod_Type>
class PodContainer
{
public:
//stl-like iterators for compatibility with stl-algorithms
Pod_Type* begin();
Pod_Type* end();
//special "insertion" function that inserts a non-initialized pod
Pod_Type* new_empty();
//This "something" is my problem. I guess this has to be a functor.
//More on this later
Something generic_insert;
private:
Pod_Type* mStorage; //Allocated space for pods
};
//Simple structure to use as example
struct PodA
{
int x,y,z;
};
//Function to initialize a pod of type podA with the given params
inline
init_podA( podA* ptr, int a, int b, int c)
{
ptr->x = a; ptr->y = b; ptr->z = c;
}
int main()
{
//Create a buffer
PodContainer<podA> buff;
//Insert some elements and intialize them "by hand"
for (int i=0; i < 10 ; ++i)
{
init_podA( buff.new_empty(), 1,2,3);
}
}
Обратите внимание, что все проблемы управления памятью для класса контейнера решены (я уже тщательно его тестировал), и сам контейнер отлично подходит для моей реальной проблемы.
Теперь самое интересное. Я хочу, чтобы это "что-то" вызывало мою функцию init_podA из контейнера. Очевидно, что я не могу связать это внутри класса Buffer, потому что я даже не знаю, сколько параметров понадобится следующей функции init_xxx, которая понадобится пользователю для его типа pod. Я начал играть с идеей передачи второго шаблона параметра в класс PodContainer, где второй является классом признаков, который я могу запросить для функтора, который оборачивает вызов к реальной функции инициализации. В классе PodContainer я мог бы запросить класс признаков и сохранить созданный там функтор, который будет вызываться пользователями и создавать впечатление функции-члена.
Идея заключалась в том, что я бы использовал эти черты, как это:
template<typename PodType, typename PodTraits = MyPodTraits<PodType> >
class PodContainer
{
PodContainer():
generic_insert(PodTraits::get_inserter(this))
//The rest of the PodContainer definition
....
//And the user of the container would see this
PodContainer<PodA> buffer;
buffer.generic_insert(a,b,c); //Calls buffer->new_empty and initializes a pod
Это вообще возможно? Я думаю, я бы использовал некоторую хитрость boost::bind, я прав? Какой тип функтора, чтобы я мог получить его в контейнере? Есть ли лучший вариант??
Спасибо!!
Изменить: Обратите внимание, что я не могу использовать C++11:(
1 ответ
Пока вы не можете использовать C++11 (и шаблоны с переменным числом аргументов), вы всегда можете пойти по сложному пути и обеспечить перегрузку для каждого возможного числа параметров. Вот так:
void generic_insert(void (*init)(PodType*)) { init(new_empty()); }
template<typename A1>
void generic_insert(void (*init)(PodType*, A1), A1 a1) { init(new_empty(), a1); }
/* and so on ... */