Correctly handle temporaries in container views

Move temporaries into the view itself and keep a reference on
non temporaries
This commit is contained in:
Maxime Coste 2016-03-24 22:14:18 +00:00
parent ccb53eca42
commit 50a64a0544

View File

@ -22,19 +22,26 @@ template<typename Container>
struct ReverseView struct ReverseView
{ {
using iterator = decltype(std::declval<Container>().rbegin()); using iterator = decltype(std::declval<Container>().rbegin());
ReverseView(Container& container) : m_container(container) {}
iterator begin() { return m_container.rbegin(); } iterator begin() { return m_container.rbegin(); }
iterator end() { return m_container.rend(); } iterator end() { return m_container.rend(); }
private: Container m_container;
Container& m_container;
}; };
template<typename C>
using RemoveReference = typename std::remove_reference<C>::type;
struct ReverseFactory struct ReverseFactory
{ {
template<typename Container> template<typename Container>
ReverseView<Container> operator()(Container&& container) const ReverseView<RemoveReference<Container>> operator()(Container&& container) const
{
return {std::move(container)};
}
template<typename Container>
ReverseView<Container&> operator()(Container& container) const
{ {
return {container}; return {container};
} }
@ -84,14 +91,10 @@ struct FilterView
const FilterView& m_view; const FilterView& m_view;
}; };
FilterView(Container& container, Filter filter)
: m_container(container), m_filter(std::move(filter)) {}
Iterator begin() const { return {*this, m_container.begin(), m_container.end()}; } Iterator begin() const { return {*this, m_container.begin(), m_container.end()}; }
Iterator end() const { return {*this, m_container.end(), m_container.end()}; } Iterator end() const { return {*this, m_container.end(), m_container.end()}; }
private: Container m_container;
Container& m_container;
Filter m_filter; Filter m_filter;
}; };
@ -99,7 +102,10 @@ template<typename Filter>
struct FilterFactory struct FilterFactory
{ {
template<typename Container> template<typename Container>
FilterView<Container, Filter> operator()(Container&& container) const { return {container, std::move(m_filter)}; } FilterView<Container&, Filter> operator()(Container& container) const { return {container, std::move(m_filter)}; }
template<typename Container>
FilterView<RemoveReference<Container>, Filter> operator()(Container&& container) const { return {std::move(container), std::move(m_filter)}; }
Filter m_filter; Filter m_filter;
}; };
@ -142,14 +148,10 @@ struct TransformView
const TransformView& m_view; const TransformView& m_view;
}; };
TransformView(Container& container, Transform transform)
: m_container(container), m_transform(std::move(transform)) {}
Iterator begin() const { return {*this, m_container.begin()}; } Iterator begin() const { return {*this, m_container.begin()}; }
Iterator end() const { return {*this, m_container.end()}; } Iterator end() const { return {*this, m_container.end()}; }
private: Container m_container;
Container& m_container;
Transform m_transform; Transform m_transform;
}; };
@ -157,7 +159,10 @@ template<typename Transform>
struct TransformFactory struct TransformFactory
{ {
template<typename Container> template<typename Container>
TransformView<Container, Transform> operator()(Container&& container) const { return {container, std::move(m_transform)}; } TransformView<Container&, Transform> operator()(Container& container) const { return {container, std::move(m_transform)}; }
template<typename Container>
TransformView<RemoveReference<Container>, Transform> operator()(Container&& container) const { return {std::move(container), std::move(m_transform)}; }
Transform m_transform; Transform m_transform;
}; };
@ -166,7 +171,6 @@ template<typename Transform>
inline ContainerView<TransformFactory<Transform>> transform(Transform t) { return {{std::move(t)}}; } inline ContainerView<TransformFactory<Transform>> transform(Transform t) { return {{std::move(t)}}; }
template<typename Container1, typename Container2> template<typename Container1, typename Container2>
struct ConcatView struct ConcatView
{ {