问题
I have a legacy code in which the interface is defined for pointer only and I am trying to adapt some functions to take iterators.
In the answers to this question Address of a dereferenced InputIterator? The case of istream_iterator
it was noted that std::istream_iterators
are InputIterator
.
However they are special among InputIterator
s, because their dereference is guarantied to generate a language reference T const&
.
The code for a general input iterator would look like this, notice that I have to generate a copy of the value type to take the address.
#include<iostream>
#include<iterator>
#include<sstream>
void f_legacy(double const* t){
std::cout << *t << std::endl;
};
template<class InputIt>
void f_aux(InputIt it, std::input_iterator_tag){
using value_type = typename std::iterator_traits<InputIt>::value_type;
value_type v = *it; // creates a local copy, *might be* unnecessary
f_legacy(std::addressof(v));
}
template<class It>
void f(It it){
f_aux(it, typename std::iterator_traits<It>::iterator_category{});
}
int main(){
double d = 5.;
std::istringstream iss("1 2 3");
std::istream_iterator<double> it(iss);
f_legacy(&d);
f(it);
}
However for std::istream_iterator
this is not optimal because an unnecessary copy is made. (I don't know if it can be optimized, but that is another question.)
So I could add an overload to handle the optimizations for istream_iterator
.
void f(std::istream_iterator<double> it){
f_legacy(std::addressof(*it));
}
or more verbose
void f(std::istream_iterator<double> it){
double const& v = *it; // no copy is made
f_legacy(std::addressof(v));
}
The question is, can I just use this following version of f
without writing an overload of istream_iterator
?
template<class InputIt>
void f_aux(InputIt it, std::input_iterator_tag){
using value_type = typename std::iterator_traits<InputIt>::value_type;
value_type const& v = *it; // a "copy" is made only if necessary
f_legacy(std::addressof(v));
}
I think this should work due to https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ , but I am not sure if it applies.
or even this one liner:
template<class InputIt>
void f_aux(InputIt it, std::input_iterator_tag){
using value_type = typename std::iterator_traits<InputIt>::value_type;
f_legacy(std::addressof(static_cast<value_type const&>(*it)));
}
Note: In the real code all the functions are templated, double
is just a placeholder here.
来源:https://stackoverflow.com/questions/49287221/optimize-inputiterator-dereference-without-making-a-copy-if-possible