You can't make an istringstream read from any external source: it always makes a copy, even of a single string. You can, however, make a stream that reads from any data source by making your own streambuf class and making an istream from a pointer to an instance of it. A minimal version needs only one method overridden:
#include<streambuf>
#include<string>
#include<vector>
struct stringsbuf : std::streambuf {
stringsbuf(const std::string *b,const std::string *e) : ss(b),se(e) {}
stringsbuf(const std::vector<std::string> *v) : // pointer vs. temporaries
ss(&v->front()),se(ss+v->size()) {}
int_type underflow() override {
while(ss!=se) {
auto &s=*ss++;
if(s.empty()) continue;
char *p=const_cast<char*>(s.data());
setg(p,p,p+s.size());
return *p;
}
return traits_type::eof();
}
private:
const std::string *ss,*se; // next string to load, and past-the-end string
};
This could of course be made more efficient and featureful by adding one or more of xsgetn, seekoff, seekpos, and showmanyc. It could also be made generic (not only on character type, but also by accepting any string-valued iterators).
The elegance here lies in the fact that no concatenated string is ever constructed (except perhaps by the client that reads from an istream based on a stringsbuf).