lib/expchain.cpp

The following code example is taken from the book
C++23 - The Complete Guide by Nicolai M. Josuttis, Leanpub, 2026
The code is licensed under a Creative Commons Attribution 4.0 International License. Creative Commons License

// raw code

#include <iostream>
#include <string>
#include <sstream>
#include <expected>
#include <utility>  // for in_range<>()
#include <cctype>   // for isdigit()

// read next line (might have no data):
std::expected<std::string, std::string> readLine(std::istream& is)
{
  std::string row;
  if (std::getline(is, row)) {
    if (!row.empty()) {
      return row;
    }
    else {
      return std::unexpected("line is empty");  
    }
  }
  return std::unexpected("no line");
}

// convert string to int (might not be a valid int):
std::expected<int, std::string> asInt(const std::string& s)
{
  // is the string a valid int (at the beginning)?
  char first = s[0];
  if (first == '-') first = s[1];
  if (!std::isdigit(first)) {
    return std::unexpected("\"" + s + "\" is no valid int");
  }

  return std::stoi(s);
}

// square an int value (might overflow):
std::expected<unsigned, std::string> square(int val)
{
  if (std::in_range<unsigned>(1LL * val * val)) {
    return static_cast<unsigned>(val * val);
  }
  else {
    return std::unexpected(std::format("overflow for {}", val));
  }
}


void process(std::istream& strm)
{
  while (strm) {
    std::expected expLine = readLine(strm);    // read next line
    if (!expLine) {
      std::cout << "ERROR: " << expLine.error() << '\n';  
    }
    else {
      std::expected expInt = asInt(*expLine);    // convert to int
      if (!expInt) {
        std::cout << "ERROR: " << expInt.error() << '\n';  
      }
      else {
        std::expected expSquare = square(*expInt);   // compute square
        if (!expSquare) {
          std::cout << "ERROR: " << expSquare.error() << '\n';
        }
        else {
          std::cout << *expSquare << '\n';    
        }
      }
    }
  }
}

int main()
{
  // simulate input stream:
  static std::stringstream sStrm{"7\n42\n100000\nhi\n\n-11"};

  process(sStrm);
}