1 /*
2    Copyright (C) 2012 - 2018 by Mark de Wever <koraq@xs4all.nl>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "utils/type_trait_aliases.hpp"
18 
19 #include <type_traits>
20 
21 namespace utils
22 {
23 /**
24  * Helper struct to clone the constness of one type to another.
25  *
26  * @warning It seems @c *this in a const member function is not a const object,
27  * use @c this, which is a pointer to a const object.
28  *
29  * @tparam D                      The destination type, it should have no
30  *                                cv-qualifier and not be a pointer or
31  *                                reference.
32  * @tparam S                      The source type, this type may be a pointer
33  *                                or reference and obviously is allowed to have
34  *                                a cv-qualifier, although @c volatile has no
35  *                                effect.
36  */
37 template<typename D, typename S>
38 struct const_clone
39 {
40 	static const bool is_source_const =
41 		std::is_const<
42 			utils::remove_pointer_t<
43 				utils::remove_reference_t<S>
44 			>
45 		>::value;
46 
47 	/** The destination type, possibly const qualified. */
48 	using type =
49 		utils::conditional_t<is_source_const, const D, D>;
50 
51 	/** A reference to the destination type, possibly const qualified. */
52 	using reference =
53 		utils::conditional_t<is_source_const, const D&, D&>;
54 
55 	/** A pointer to the destination type, possibly const qualified. */
56 	using pointer =
57 		utils::conditional_t<is_source_const, const D*, D*>;
58 };
59 
60 template<typename D, typename S>
61 using const_clone_t = typename const_clone<D, S>::type;
62 
63 template<typename D, typename S>
64 using const_clone_ref = typename const_clone<D, S>::reference;
65 
66 template<typename D, typename S>
67 using const_clone_ptr = typename const_clone<D, S>::pointer;
68 
69 } // namespace utils
70