Files
scylladb/utils/immutable-collection.hh
Pavel Emelyanov c2a36f5668 utils: Introduce immutable_collection<>
Wokring with collections can be done via const- and non-const
references. In the former case the collection can only be read
from (find, iterate, etc) in the latter it's possible to alter
the collection (erase elements from or insert them into). Also
the const-ness of the collection refernece is transparently
inherited by the returned _elements_ of the collection, so when
having a const reference on a collection it's impossible to
modify the found element.

This patch introduces a immutable_collection -- a wrapper over
a random collection that makes sure the collection itself is not
modified, but the obtained from it elements can be non-const.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
2021-07-27 20:06:53 +03:00

89 lines
2.8 KiB
C++

/*
* Copyright (C) 2021-present ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <type_traits>
#include <seastar/util/concepts.hh>
namespace utils {
/*
* Wraps a collection into immutable form.
*
* Immutability here means that the collection itself cannot be modified,
* i.e. adding or removing elements is not possible. Read-only methods such
* as find(), begin()/end(), lower_bound(), etc. are available and are
* transparently forwarded to the underlying collection. Return values from
* those methods are also returned as-is so it's pretty much like a const
* reference on the collection.
*
* The important difference from the const reference is that obtained
* elements or iterators are not necessarily const too, so it's possible
* to modify the found or iterated over elements.
*/
template <typename Collection>
class immutable_collection {
Collection& _col;
public:
immutable_collection(Collection& col) noexcept : _col(col) {}
#define DO_WRAP_METHOD(method, is_const) \
template <typename... Args> \
auto method(Args&&... args) is_const noexcept(noexcept(std::declval<is_const Collection>().method(args...))) { \
return _col.method(std::forward<Args>(args)...); \
}
#define WRAP_CONST_METHOD(method) \
DO_WRAP_METHOD(method, const)
#define WRAP_METHOD(method) \
WRAP_CONST_METHOD(method) \
DO_WRAP_METHOD(method, )
WRAP_METHOD(find)
WRAP_METHOD(lower_bound)
WRAP_METHOD(upper_bound)
WRAP_METHOD(slice)
WRAP_METHOD(upper_slice)
WRAP_CONST_METHOD(empty)
WRAP_CONST_METHOD(size)
WRAP_CONST_METHOD(calculate_size)
WRAP_CONST_METHOD(external_memory_usage)
WRAP_METHOD(begin)
WRAP_METHOD(end)
WRAP_METHOD(rbegin)
WRAP_METHOD(rend)
WRAP_CONST_METHOD(cbegin)
WRAP_CONST_METHOD(cend)
WRAP_CONST_METHOD(crbegin)
WRAP_CONST_METHOD(crend)
#undef WRAP_METHOD
#undef WRAP_CONST_METHOD
#undef DO_WRAP_METHOD
};
} // namespace utils