1

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

在这个问题的答案中Address of a dereferenced InputIterator? 注意到istream_iterator 的情况std::istream_iteratorsInputIterator. 但是它们在InputIterators 中是特殊的,因为它们的取消引用保证生成语言引用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这里只是一个占位符。

4

0 回答 0