Two error-reporting conventions for a command-parser I need to implement some function and I would like to report about a fail made inside a function. If function doesn't fail I need to get a some result (for example, std::string). I see two ways to implement function:


// 1. report with exception
std::string foo() {
  std::string ret;
  ... // solving str
  if (is_fail())
    throw ...;
  return ret;
}

// 2. report with return value
bool foo(const std::string &amp;str) {
  ... // solving str
  return is_fail();
}



What way is more preferable and why? Or, maybe, there is the best way I didn't write?



The following is the original code for both cases.

namespace fs = boost::filesystem;
namespace po = boost::program_options;

/////////////////////////////////////////////////
// 1. report with exception
fs::path parse(int argc, char *argv[]) {
  fs::path ret;
  po:options_description desc("Program options");
  desc.add_options()
    ("help,h", "Show help")
    ("output,o", po::value&lt;fs::path&gt;(&amp;ret), "Output folder")
    ;
  po::variables_map vm;
  const po::parsed_options opts = po::command_line_parser(argc, argv).options(desc).run();
  po::store(opts, vm);
  ...
  return ret;
}

int main(int argc, char *argv[]) {
  fs::path output;
  try {
    output = parse(argc, argv);
  } catch (const std::exception &amp;e) { 
    cout &lt;&lt; e.what() &lt;&lt; std::endl;
    return 1;
  }
  ...
}

//////////////////////////////////////////////////////
// 2. report with return value
bool parse(int argc, char *argv[], fs::path &amp;output) {
  po:options_description desc("Program options");
  desc.add_options()
    ("help,h", "Show help")
    ("output,o", po::value&lt;fs::path&gt;(&amp;output), "Output folder")
    ;
  po::variables_map vm;
  try {
    const po::parsed_options opts = po::command_line_parser(argc, argv).options(desc).run();
    po::store(opts, vm);
  } catch (const std::exception &amp;e) { 
    cout &lt;&lt; e.what() &lt;&lt; endl;
    return false; 
  }
  ...
  return true;
}

int main(int argc, char *argv[]) {
  fs::path output;
  if (!parse(argc, argv, output))
    return 1;
  ...
}




Actually speed is not critical here and parse function performs just once. Maybe, there is not big deal to choose right answer. However, I would like to know what good practice is.
Given the additional context, I don't think exceptions are warranted here.

Exceptions are most useful when the code that generates an error condition is far away from the code that handles that error condition.

In this code, the error condition is handled immediately after it's generated.

So I'd prefer the bool-returning version rather than throw/catch.