// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_UTIL_INSTANCE_MULTIMAP_H namespace ircd { inline namespace util { template> struct instance_multimap; }} /// See instance_list for purpose and overview. template struct ircd::util::instance_multimap { static std::multimap map; protected: typename decltype(map)::iterator it; instance_multimap(const typename decltype(map)::const_iterator &hint, K&& key); instance_multimap(K&& key); instance_multimap(instance_multimap &&) noexcept; instance_multimap(const instance_multimap &); instance_multimap &operator=(instance_multimap &&) noexcept; instance_multimap &operator=(const instance_multimap &); ~instance_multimap() noexcept; }; template ircd::util::instance_multimap::instance_multimap(K&& key) :it { map.emplace(std::forward(key), static_cast(this)) } {} template ircd::util::instance_multimap::instance_multimap(const typename decltype(map)::const_iterator &hint, K&& key) :it { map.emplace_hint(hint, std::forward(key), static_cast(this)) } {} template ircd::util::instance_multimap::instance_multimap(instance_multimap &&other) noexcept :it { std::move(other.it) } { if(it != end(map)) { it->second = static_cast(this); other.it = end(map); } } template ircd::util::instance_multimap::instance_multimap(const instance_multimap &other) :it { other.it != end(map)? map.emplace_hint(other.it, other.it->first, static_cast(this)): end(map) } {} template ircd::util::instance_multimap & ircd::util::instance_multimap::operator=(instance_multimap &&other) noexcept { this->~instance_multimap(); it = std::move(other.it); if(it != end(map)) it->second = static_cast(this); other.it = end(map); return *this; } template ircd::util::instance_multimap & ircd::util::instance_multimap::operator=(const instance_multimap &other) { this->~instance_multimap(); it = other.it != end(map)? map.emplace_hint(other.it, other.it->first, static_cast(this)): end(map); return *this; } template ircd::util::instance_multimap::~instance_multimap() noexcept { if(it != end(map)) map.erase(it); }