iterator/zip: avoid std::forward_as_tuple for zip value_type
This tends to result in references to temporaries higher up the stack being returned. decltype on the iterator dereference is a more reliable method to determine the return type.
This commit is contained in:
parent
f1aa7fa775
commit
ec1f354d16
@ -44,11 +44,13 @@ namespace cruft::iterator {
|
|||||||
// pressing need for this functionality.
|
// pressing need for this functionality.
|
||||||
using iterator_category = std::input_iterator_tag;
|
using iterator_category = std::input_iterator_tag;
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
using value_type = std::tuple<
|
using value_type = std::tuple<
|
||||||
typename std::iterator_traits<
|
typename std::iterator_traits<
|
||||||
std::tuple_element_t<IndexV, IteratorT>
|
std::tuple_element_t<IndexV, IteratorT>
|
||||||
>::reference...
|
>::reference...
|
||||||
>;
|
>;
|
||||||
|
|
||||||
using reference = value_type;
|
using reference = value_type;
|
||||||
using pointer = value_type*;
|
using pointer = value_type*;
|
||||||
|
|
||||||
@ -68,19 +70,39 @@ namespace cruft::iterator {
|
|||||||
zipped_iterator operator++ (int);
|
zipped_iterator operator++ (int);
|
||||||
|
|
||||||
|
|
||||||
decltype(auto)
|
// Do NOT use std::forward_as_tuple here. It favours rvalue
|
||||||
|
// references which aren't useful after we've returned. decltype
|
||||||
|
// gives us lvalues and lvalue-references.
|
||||||
|
//
|
||||||
|
// If you insist on using another approach then you should test
|
||||||
|
// under a sanitizer (debug and release) before you commit the
|
||||||
|
// changes.
|
||||||
|
auto
|
||||||
operator* (void)
|
operator* (void)
|
||||||
{
|
{
|
||||||
return std::forward_as_tuple (
|
return std::tuple<
|
||||||
|
decltype (*std::get<IndexV> (m_iterators))...
|
||||||
|
> (
|
||||||
*std::get<IndexV> (m_iterators)...
|
*std::get<IndexV> (m_iterators)...
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
decltype (auto)
|
// Do NOT use std::forward_as_tuple here. It favours rvalue
|
||||||
|
// references which aren't useful after we've returned. decltype
|
||||||
|
// gives us lvalues and lvalue-references.
|
||||||
|
//
|
||||||
|
// If you insist on using another approach then you should test
|
||||||
|
// under a sanitizer (debug and release) before you commit the
|
||||||
|
// changes.
|
||||||
|
auto
|
||||||
operator* (void) const
|
operator* (void) const
|
||||||
{
|
{
|
||||||
return std::forward_as_tuple (
|
return std::tuple<
|
||||||
|
std::add_const_t<
|
||||||
|
decltype(*std::get<IndexV> (m_iterators))
|
||||||
|
>...
|
||||||
|
> (
|
||||||
*std::get<IndexV> (m_iterators)...
|
*std::get<IndexV> (m_iterators)...
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user