Я часто нахожу, что хочу написать такой код:
class MyClass
{
public:
void addObject(std::unique_ptr<Object>&& newObject);
void removeObject(const Object* target);
private:
std::set<std::unique_ptr<Object>> objects;
};
Однако большая часть интерфейса std:: set выглядит бесполезной с помощью std:: unique_ptrs, так как для функций поиска требуются параметры std:: unique_ptr (которых я, очевидно, не имею, потому что они принадлежат самому набору).
Я могу думать о двух основных решениях этого.
-
Создайте временный уникальный_ptr для поиска. Например, вышеупомянутый removeObject() может быть реализован следующим образом:
void MyClass::removeObject(const Object* target) { std::unique_ptr<Object> targetSmartPtr(target); objects.erase(targetSmartPtr); targetSmartPtr.release(); }
-
Замените набор на карту исходных указателей на unique_ptrs.
// ... std::map<const Object*, std::unique_ptr<Object>> objects; };
Однако, оба кажутся мне немного глупыми. В решении 1 erase() не является исключением, поэтому временный unique_ptr может удалить объект, который он действительно не имеет, и 2 требует ненужного хранения для контейнера.
Я знаю о контейнерах указателей Boost, но их текущие функции ограничены по сравнению с современными стандартными библиотечными контейнерами С++ 11.
Недавно я читал о С++ 14 и наткнулся на "Добавление гетерогенного поиска сравнений в ассоциативные контейнеры". Но формируйте мое понимание этого, типы поиска должны быть сопоставимы с типами ключей, но исходные указатели не сопоставимы с unique_ptrs.
Кто-нибудь знает более элегантное решение или предстоящее дополнение к С++, которое решает эту проблему?