C++, function that can take either ifstream or istringstream
Asked Answered
P

1

19

I have a function do_something that reads unsigned characters from a stream.

The stream can be created from a file given the file name. Or it can be created from the given string by considering it as data. I would like to reuse the function in both cases.

The code below gives an error in the second case: "error C2664: 'do_something: cannot convert argument 1 from 'std::basic_istringstream' to 'std::basic_istream'".

What is the proper way to do this?

static void do_something(std::basic_istream<unsigned char>& in)
{
   in.get();
}

static void string_read(unsigned char* in)
{
   std::basic_ifstream<unsigned char> file(std::string("filename"));
   do_something(file);

   std::basic_istringstream<unsigned char> str(std::basic_string<unsigned char>(in));
   do_something(str);
}
Pindaric answered 17/7, 2020 at 18:28 Comment(0)
A
22

Your code is experiencing something called a vexing parse. The line:

std::basic_istringstream<unsigned char> str(std::basic_string<unsigned char>(in));

is interpreted as a function declaration. str here is a function that returns a std::istringstream and takes as its parameter a variable of type std::string called in. So when you pass it into the function there's an obvious type mismatch.

To change it into a variable declaration you can use curly braces:

std::basic_istringstream<unsigned char> str{std::basic_string<unsigned char>(in)};
Anemograph answered 17/7, 2020 at 18:37 Comment(2)
The MOST vexing parse, I dare say. Also, CLang gives a nice warning on this with -Wextra.Denman
There is no need for all the explicit type conversions: static void string_read(unsigned char* in) { std::basic_ifstream<unsigned char> file("filename"); do_something(file); std::basic_istringstream<unsigned char> str(in); do_something(str); } Now there is no vexing parse to begin with.Lauree

© 2022 - 2024 — McMap. All rights reserved.