如果可能,优化InputIterator取消引用而不进行复制?

时间:2018-03-14 20:37:19

标签: c++ dereference object-lifetime istream-iterator const-reference

我有一个遗留代码,其中接口仅为指针定义,我正在尝试调整一些函数以获取迭代器。

在这个问题的答案中Address of a dereferenced InputIterator? The case of istream_iterator 有人指出std::istream_iteratorsInputIterator。 但是它们在InputIterator中是特殊的,因为它们的取消引用可以保证生成语言参考T const&

一般输入迭代器的代码如下所示,请注意我必须生成值类型的副本以获取地址。

#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);
}

但是对于std::istream_iterator,这不是最佳的,因为会产生不必要的副本。 (我不知道它是否可以优化,但这是另一个问题。) 所以我可以添加一个重载来处理istream_iterator的优化。

void f(std::istream_iterator<double> it){
    f_legacy(std::addressof(*it));
}

或更详细

void f(std::istream_iterator<double> it){
    double const& v = *it; // no copy is made
    f_legacy(std::addressof(v));
}

问题是,我可以使用以下版本的f 编写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));
}

我认为这应该适用于https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/,但我不确定它是否适用。

甚至是这一个班轮:

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)));
}

注意:在实际代码中,所有函数都是模板化的,double只是一个占位符。

0 个答案:

没有答案