I have code like this
std::ifstream file(filename, std::ios_base::in);
if(file.good())
{
file.imbue(std::locale(std::locale(), new delimeter_tokens()));
for(auto& entry : std::istream_iterator<std::string>(file))
{
std::cout << entry << std::endl;
}
}
file.close();
where std::istream_iterator<std::string>
's begin()
and end()
are defined as follows
template<class T>
std::istream_iterator<T> begin(std::istream_iterator<T>& stream)
{
return stream;
}
template<class T>
std::istream_iterator<T> end(std::istream_iterator<T>& stream)
{
return std::istream_iterator<T>();
}
which is what Mark Nelson has also written about in Dr. Dobb's here. Alas, the code fails to compile on my Visual Studio 2012 with error messages
error C3312: no callable 'begin' function found for type 'std::istream_iterator<_Ty>'
and
error C3312: no callable 'end' function found for type 'std::istream_iterator<_Ty>'
Question: Is there something I haven't noticed, bug in the compiler (unlikely, but just in case) or... Well, any ideas?
This questions is cleaned up considerably, as advised by Xeo. To provide more background and references this is related to my other question on Stackoverflow, I was wondering how to make line based parsing cleaner than the usual loops. A bit of coding and checking from the internet, and I had a working sketch as follows
std::ifstream file(filename, std::ios_base::in);
if(file.good())
{
file.imbue(std::locale(std::locale(), new delimeter_tokens()));
for(auto& entry : istream_range<std::string>(file)
{
std::cout << entry << std::endl;
}
}
file.close();
but there was slight snag I tried to remedy. I think it would look more natural to write as in the code that fails to compile and not like
for(auto& entry : istream_range<std::string>(file)
Please, take a note of the different iterator. The delimeter_tokens is defined like Nawaz kindly has shown here (code not duplicated) and istream_range as in Code Synthesis blog here. I think the begin and end implementations should work, as advertised in the aforementioned Code Synthesis blog post
The last rule (the fallback to the free-standing begin()and end() functions) allows us to non-invasively adapt an existing container to the range-based for loop interface.
Thus my question with all the (ir)relevant background.