Reputation: 15746
I usually use std::getline
to read console input for online programming challenges, I've solved quite a bunch now and I've become weary of writing multiple std::getline(std::cin, str1); std::getline(std::cin, str2); std::getline(std::cin, str3);...
So I was writing my own multiple readlines using variadic templates and I just need a quick review if this stands correct, because it seems to me that getlines(first)
is not returned? Would while
still evaluate if nothing is input on s1
?
#include <iostream>
#include <string> //getline
#include <type_traits> //std::is_same
template<typename F>
std::istream& getlines(F& first)
{
return std::getline(std::cin, first);
}
template<typename F, typename...O>
std::istream& getlines(F& first, O&... others)
{
static_assert(std::is_same_v<decltype(first), std::string&>, "error: template getlines must be of std::string type");
getlines(first); //how is this returned?
return getlines(others...);
}
int main()
{
std::string s1, s2, s3;
while (getlines(s1, s2, s3))
{
std::cout << s1 << s2 << s3 << std::endl;
}
}
Upvotes: 1
Views: 84
Reputation: 16156
it seems to me that
getlines(first)
is not returned? Would while still evaluate if nothing is input ons1
?
The return value of getlines is istream &
... and it is indeed not used. That doesn't matter much, though, because you have a reference to that stream eitherway (std::cin
). So even if s1
can not be set due to EOF or some other condition, the corresponding flags are set in std::cin
and thus once you return it (which you do at the end) it's tested in the condition of the while
loop.
The missed opportunity here is that you can exit early when that first getlines
already fails. E.g:
template<typename F>
std::istream& getlines(F& first)
{
return std::getline(std::cin, first);
}
template<typename F, typename...O>
std::istream& getlines(F& first, O&... others)
{
static_assert(std::is_same_v<decltype(first), std::string&>, "error: template getlines must be of std::string type");
if (! getlines(first)) return std::cin;
return getlines(others...);
}
Btw, here's what I came up with:
template<typename... Strings>
std::istream & getlines(Strings &... strings) {
for (auto & str : {std::ref(strings)...}) {
if (! std::getline(std::cin, str.get())) break;
}
return std::cin;
}
Upvotes: 1