我有一个遗留代码,其中接口仅为指针定义,我正在尝试调整一些函数以获取迭代器。
在这个问题的答案中Address of a dereferenced InputIterator? The case of istream_iterator
有人指出std::istream_iterators
是InputIterator
。
但是它们在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
只是一个占位符。