Я работаю над контейнером, код которого похож на следующий псевдокод:
#define LARGE_INSERT_MACRO (ASSIGNMENT_OBJECT) \
if (some_stuff) \
{ \
... do more stuff ... \
allocator.construct(place_to_insert_to, ASSIGNMENT_OBJECT); \
... etc ... \
} \
else if (other_stuff) \
{ \
... do different stuff ... \
allocator.construct(place_to_insert_to, ASSIGNMENT_OBJECT); \
... etc ... \
} \
else \
{ \
... do other different stuff ... \
allocator.construct(place_to_insert_to, ASSIGNMENT_OBJECT); \
... etc ... \
} \
... more stuff again... \iterator insert(the_type &object)
{
LARGE_INSERT_MACRO(object)
}iterator insert(the_type &&object)
{
LARGE_INSERT_MACRO(std::move(object))
}template<typename... Arguments> iterator emplace(Arguments... parameters)
{
LARGE_INSERT_MACRO(parameters...)
}
Учитывая тот факт, что код до и после каждого типа вставки необходим для вставки, не изменяется между типами вставки и не может быть разнесен на две отдельные функции «до и после», как этот фрагмент (псевдо) кода может быть изменилось, чтобы он больше не использовал макросы?
Как всегда, оставайтесь на теме смены макросов на другие формы кода — пожалуйста.
Ответ заключается в том, чтобы полностью сбросить большой макрос вставки и позволить чуду универсального справочного вывода сделать всю работу за вас:
template<class TheType>
iterator insert(TheType&& object) // object is deduced to be either r-value
// or l-value reference as required by context
{
if(some_stuff) {
...
return allocator.construct(place_to_insert_to, std::forward<TheType>(object));
} else {
... and so on
}
}
emplace без аргумента шаблона на сайте вызова возможна только тогда, когда это функция-член контейнера, который знает тип, который он содержит. В противном случае вы должны указать это. Опять же, обратите внимание на использование универсального ссылочного вывода для идеальной передачи аргументов.
template<class TheType, typename... Arguments>
iterator emplace(Arguments&&... parameters)
{
return insert(TheType(std::forward<Arguments>(parameters)...));
}
Других решений пока нет …