I have following function:
/// <summary>
/// Check whether next character in std::basic_istream is what expected. Skip it if so; otherwise, set fail flag.
/// </summary>
template <typename TCharType, TCharType char_>
std::basic_istream<TCharType>& skipIf(std::basic_istream<TCharType>& istream_)
{
if ((istream_ >> std::ws).peek() == char_) {
istream_.ignore();
}
else {
istream_.setstate(std::ios_base::failbit);
}
return istream_;
}
It works like this:
std::istringstream is {"some ; string"};
std::string temp;
if(is >> temp >> skipIf<char, ';'> >> temp) {
// blah blah
}
Is there way to deduce TCharType
from given char_
template parameter? It would be nice if I could write just
skipIf<';'>
-> deduced to char
skipIf<L';'>
-> deduced to wchar_t
skipIf<u';'>
-> deduced to char16_t
skipIf<U';'>
-> deduced to char32_t
You can do that with C++17's new auto
non-type template parameters. A bit of rearranging:
template <auto char_, typename TCharType = decltype(char_)>
std::basic_istream<TCharType>& skipIf(std::basic_istream<TCharType>& istream_)
{
if ((istream_ >> std::ws).peek() == char_) {
istream_.ignore();
}
else {
istream_.setstate(std::ios_base::failbit);
}
return istream_;
}
And you should get what you are after, exactly. You can probably improve it by adding a few more checks (either as a static_assert
or SFINAE) to make sure TCharType
is indeed one of the standard or extended character types, but that's the cookbook solution.