1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
| // Code compilé sur http://coliru.stacked-crooked.com/
// Version de g++ : 6.1.0
// Commande : g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
#include <memory>
#include <type_traits>
#include <vector>
/*!
* \brief Conteneur de pointeurs (nus ou intelligents) dont const est propagé jusqu'aux valeurs pointées.
* \remark Le type Container peut aussi être une référence.
*/
template<class Container>
class propagate_const_pointer_container
{
private:
typedef propagate_const_pointer_container<Container> self_type;
typedef typename std::remove_reference<Container>::type container_type;
typedef typename container_type::value_type value_type;
typedef typename std::remove_reference<
decltype(*std::declval<value_type>())>::type dereference_type;
typedef typename std::add_const<dereference_type>::type const_dereference_type;
Container m_container;
public:
constexpr propagate_const_pointer_container(const self_type&) = default;
constexpr propagate_const_pointer_container(self_type&&) = default;
self_type& operator=(const self_type&) = delete;
self_type& operator=(self_type&&) = delete;
constexpr propagate_const_pointer_container()
noexcept(std::is_default_constructible<Container>::value)
{}
constexpr explicit propagate_const_pointer_container(const Container& c)
noexcept(std::is_nothrow_copy_constructible<Container>::value) :
m_container(c)
{}
template<class Container2>
constexpr explicit propagate_const_pointer_container(Container2&& c)
noexcept(std::is_nothrow_constructible<Container, Container2&&>::value) :
m_container(std::forward<Container2>(c))
{}
dereference_type& operator[](size_t index)
noexcept(noexcept(*std::declval<Container>()[index]))
{
return *m_container[index];
}
constexpr const_dereference_type& operator[](size_t index) const
noexcept(noexcept(*std::declval<Container>()[index]))
{
return *m_container[index];
}
void push_back(const value_type& pointer)
{
m_container.push_back(pointer);
}
void push_back(value_type&& pointer)
{
m_container.push_back(std::move(pointer));
}
// Autres fonctions...
};
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
int main(int argc, char** argv)
{
std::vector<std::unique_ptr<int>> vect_unique;
vect_unique.push_back(std::make_unique<int>(0));
vect_unique.push_back(std::make_unique<int>(1));
// Objet similaire à const std::vector<std::unique_ptr<int>>,
// sauf qu'une référence constante vers lui propage const jusqu'à int.
propagate_const_pointer_container<const std::vector<std::unique_ptr<int>>> test_unique_const(std::move(vect_unique));
test_unique_const[0] += 10;
// test_unique_const.push_back(std::make_unique<int>(2)); // Ne compile pas.
const auto& const_ref_test_unique_const = test_unique_const;
// const_ref_test_unique_const[0] += 10; // Ne compile pas.
// Objet similaire à std::vector<std::unique_ptr<int>>,
// sauf qu'une référence constante vers lui propage const jusqu'à int.
propagate_const_pointer_container<std::vector<std::unique_ptr<int>>> test_unique;
test_unique.push_back(std::make_unique<int>(0));
test_unique.push_back(std::make_unique<int>(1));
test_unique[0] += 10;
test_unique[1] += 10;
const auto& const_ref_test_unique = test_unique;
// const_ref_test_unique[0] += 10; // Ne compile pas.
std::vector<int*> vect_ptr;
vect_ptr.push_back(&test_unique[0]);
vect_ptr.push_back(&test_unique[1]);
// Objet similaire à const std::vector<int*>,
// sauf qu'une référence constante vers lui propage const jusqu'à int.
propagate_const_pointer_container<const std::vector<int*>> test_ptr_const(vect_ptr); // passage par copie
test_ptr_const[0] += 100;
test_ptr_const[1] += 100;
// test_ptr_const.push_back(&test_unique[0]); // Ne compile pas.
const auto& const_ref_test_ptr_const = test_ptr_const;
// const_ref_test_ptr_const[0] += 10; // Ne compile pas.
// Objet contenant un const std::vector<int*>&.
// Une référence constante vers lui propage const jusqu'à int.
propagate_const_pointer_container<const std::vector<int*>&> test_ptr_ref_const(vect_ptr); // passage par référence constante
test_ptr_ref_const[0] += 200;
test_ptr_ref_const[1] += 200;
// test_ptr_ref_const.push_back(&test_unique[0]); // Ne compile pas.
const auto& const_ref_test_ptr_ref_const = test_ptr_ref_const;
// const_ref_test_ptr_ref_const[0] += 10; // Ne compile pas.
// Objet contenant un std::vector<int*>&.
// Une référence constante vers lui propage const jusqu'à int.
propagate_const_pointer_container<std::vector<int*>&> test_ptr_ref(vect_ptr); // passage par référence non constante
test_ptr_ref[0] += 1000;
test_ptr_ref[1] += 1000;
test_ptr_ref.push_back(&test_unique[0]);
const auto& const_ref_test_ptr_ref = test_ptr_ref;
// const_ref_test_ptr_ref[0] += 10; // Ne compile pas.
return 0;
}
#pragma GCC diagnostic pop |
Partager