/** Copyright (C) 2010-2024 Belledonne Communications SARL * SPDX-License-Identifier: AGPL-3.0-or-later */ /** Safely cast wrapped types to const. * * Using a wrapper type like std::shared_ptr<T> as if it was a std::shared_ptr<const T> is always safe, since we are * restricting the set of operations that can be made on it, not broadening it. * However C++'s type system does not allow for such casts. * * You could use reinterpret_cast directly, but that would be dangerous if the underlying type is later changed. (e.g. * std::map<std::shared_ptr<T>> -> std::unordered_map<std::shared_ptr<T>>). * The functions in this file provide a (non-exhaustive) list of safe casts, while ensuring your code still type-checks * in a sane way. */ #pragma once #include <array> #include <map> #include <memory> #include <type_traits> #include <unordered_map> namespace flexisip { template <typename, typename = void> constexpr bool is_interior_const = true; template <typename T> constexpr bool is_interior_const<T, std::void_t<decltype(*std::declval<T>() = std::declval<decltype(*std::declval<T>())>())>> = false; template <typename T> struct add_interior_const { static_assert(is_interior_const<T>); using type = T; }; template <typename T> using add_interior_const_t = typename add_interior_const<T>::type; template <template <typename...> class Tmpl, typename... Args> struct add_interior_const<Tmpl<Args...>> { static_assert(is_interior_const<Tmpl<Args...>>); using type = Tmpl<add_interior_const_t<Args>...>; }; template <typename T> struct add_interior_const<std::unique_ptr<T>> { using type = std::unique_ptr<std::add_const_t<add_interior_const_t<T>>>; }; template <typename T> struct add_interior_const<std::weak_ptr<T>> { using type = std::weak_ptr<std::add_const_t<add_interior_const_t<T>>>; }; template <typename T> struct add_interior_const<std::shared_ptr<T>> { using type = std::shared_ptr<std::add_const_t<add_interior_const_t<T>>>; }; template <typename T, std::size_t S> struct add_interior_const<std::array<T, S>> { using type = std::array<add_interior_const_t<T>, S>; }; template <typename T> const add_interior_const_t<T>& castToConst(const T& t) { return reinterpret_cast<const add_interior_const_t<T>&>(t); } } // namespace flexisip