diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4cf32cbe..9ac43be6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -63,7 +63,11 @@ jobs: Windowslatest: vmImage: 'windows-2019' cli11.std: 20 - cli11.options: -DCMAKE_CXX_FLAG="/std:c++latest" + cli11.options: -DCMAKE_CXX_FLAGS="/std:c++latest /EHsc" + Linux17nortti: + vmImage: 'ubuntu-latest' + cli11.std: 17 + cli11.options: -DCMAKE_CXX_FLAGS="-fno-rtti" pool: vmImage: $(vmImage) steps: diff --git a/book/chapters/config.md b/book/chapters/config.md index cfd570ac..153dc7c5 100644 --- a/book/chapters/config.md +++ b/book/chapters/config.md @@ -115,7 +115,8 @@ The default configuration file will read TOML files, but will write out files in ```cpp app.config_formatter(std::make_shared()); ``` -which makes use of a predefined modification of the ConfigBase class which INI also uses. + +which makes use of a predefined modification of the ConfigBase class which INI also uses. If a custom formatter is used that is not inheriting from the from ConfigBase class `get_config_formatter_base() will return a nullptr if RTTI is on (usually the default), or garbage if RTTI is off, so some care must be exercised in its use with custom configurations. ## Custom formats diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 55d31dec..bd3bb82b 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -1314,15 +1314,15 @@ class App { int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const { /// Avoid printing anything if this is a CLI::RuntimeError - if(dynamic_cast(&e) != nullptr) + if(e.get_name() == "RuntimeError") return e.get_exit_code(); - if(dynamic_cast(&e) != nullptr) { + if(e.get_name() == "CallForHelp") { out << help(); return e.get_exit_code(); } - if(dynamic_cast(&e) != nullptr) { + if(e.get_name() == "CallForAllHelp") { out << help("", AppFormatMode::All); return e.get_exit_code(); } @@ -1524,7 +1524,12 @@ class App { /// Access the config formatter as a configBase pointer std::shared_ptr get_config_formatter_base() const { + // This is safer as a dynamic_cast if we have RTTI, as Config -> ConfigBase +#if defined(__cpp_rtti) || (defined(__GXX_RTTI) && __GXX_RTTI) || (defined(_HAS_STATIC_RTTI) && (_HAS_STATIC_RTTI == 0)) return std::dynamic_pointer_cast(config_formatter_); +#else + return std::static_pointer_cast(config_formatter_); +#endif } /// Get the app or subcommand description diff --git a/include/CLI/Option.hpp b/include/CLI/Option.hpp index 2e029303..55011cfb 100644 --- a/include/CLI/Option.hpp +++ b/include/CLI/Option.hpp @@ -506,7 +506,7 @@ class Option : public OptionBase