为什么不推导出模板参数?

时间:2014-01-07 16:11:12

标签: c++ c++11

我正在使用istream_iterator从我的文件中插入内容。我也使用std::copy算法。

所以我们知道istream_iterator将一个流作为参数:

std::istream_iterator<int> it = file;

我可以直接传递流,但为什么这里不起作用?

#include <fstream>
#include <vector>

int main()
{
    std::ifstream infile("in.txt");
    std::vector<int> v;

    std::copy(infile, std::istream_iterator<int>(), std::back_inserter(v));
}

我必须这样做:

std::copy(std::istream_iterator<int>(infile), std::istream_iterator<int>(), std::back_inserter(v));

但这看起来非常冗长,我觉得他们是一个更好的方式来做我正在做的事情......

3 个答案:

答案 0 :(得分:2)

问题是std::copy对传递的对象的期望。算法std::copy期望迭代器可以运行。更确切地说,前两个参数必须是“InputIterator”来读取(开始和结束),也就是说,两个对象必须满足some "concept"

可悲的是,C ++中的IO流不会自动满足InputIterator概念(同样,仍然会丢失结束迭代器),但前提是你在{{1}的实例中包装它们虽然结束迭代器是使用实例进行符号定义而不指向流。

你可以回滚std::istream_iterator<T>接受输入流而不是两个迭代器(所以这也消除了命名结束迭代器的需要):

std::copy

现在使用它非常简单:

template <class T,
          class OutputIt /* deduced */,
          class CharT    /* deduced */>
OutputIt  copy_from_istream(std::basic_istream<CharT> & stream, OutputIt out) {
    return std::copy(
        std::istream_iterator<T, CharT>(stream),
        std::istream_iterator<T>(),
        out
    );  
}

Live Demo

答案 1 :(得分:1)

这是std::copy的相关重载被声明的方式:

template< class InputIt, class OutputIt >
OutputIt copy( InputIt first, InputIt last, OutputIt d_first );

这个函数是模板化的,它将通过给出的参数推断出类型。在您的情况下,第一个参数的类型为std::basic_ifstream<...>,因此,由于第二个参数不匹配,因此会出现编译时错误。

这就是为什么你需要明确的类型。编译器不会知道你的意思。

更简单的方法是明确提供实际的模板参数:

v.assign<std::istream_iterator<int>>(infile, {});

答案 2 :(得分:0)

尝试使用vector::assign()代替copy()算法:

v.assign(std::istream_iterator<int>(infile), std::istream_iterator<int>())