Optimize InputIterator dereference without making a copy if possible?

倾然丶 夕夏残阳落幕 提交于 2019-12-24 17:30:37

问题


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 InputIterators, 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!