1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-05-02 21:53:51 +00:00

Use e.get_name instead of dynamic_cast (#467)

* Use e.get_name instead of dynamic_cast

Also use std::static_pointer_cast instead of std::dynamic_pointer_cast

Fixes #466

* feat: Allow RTTI to be turned off

* ci: Fix CXX flags

* doc: Adding update to book

Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
This commit is contained in:
Ondřej Čertík 2020-06-01 19:24:57 -06:00 committed by Henry Schreiner
parent a8185bb499
commit ccb1ccaa0a
4 changed files with 19 additions and 9 deletions

View File

@ -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:

View File

@ -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<CLI::ConfigTOML>());
```
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

View File

@ -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<const CLI::RuntimeError *>(&e) != nullptr)
if(e.get_name() == "RuntimeError")
return e.get_exit_code();
if(dynamic_cast<const CLI::CallForHelp *>(&e) != nullptr) {
if(e.get_name() == "CallForHelp") {
out << help();
return e.get_exit_code();
}
if(dynamic_cast<const CLI::CallForAllHelp *>(&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<ConfigBase> 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<ConfigBase>(config_formatter_);
#else
return std::static_pointer_cast<ConfigBase>(config_formatter_);
#endif
}
/// Get the app or subcommand description

View File

@ -506,7 +506,7 @@ class Option : public OptionBase<Option> {
/// Can find a string if needed
template <typename T = App> Option *needs(std::string opt_name) {
auto opt = dynamic_cast<T *>(parent_)->get_option_no_throw(opt_name);
auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
if(opt == nullptr) {
throw IncorrectConstruction::MissingOption(opt_name);
}
@ -548,7 +548,7 @@ class Option : public OptionBase<Option> {
/// Can find a string if needed
template <typename T = App> Option *excludes(std::string opt_name) {
auto opt = dynamic_cast<T *>(parent_)->get_option_no_throw(opt_name);
auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
if(opt == nullptr) {
throw IncorrectConstruction::MissingOption(opt_name);
}
@ -585,7 +585,7 @@ class Option : public OptionBase<Option> {
template <typename T = App> Option *ignore_case(bool value = true) {
if(!ignore_case_ && value) {
ignore_case_ = value;
auto *parent = dynamic_cast<T *>(parent_);
auto *parent = static_cast<T *>(parent_);
for(const Option_p &opt : parent->options_) {
if(opt.get() == this) {
continue;
@ -610,7 +610,7 @@ class Option : public OptionBase<Option> {
if(!ignore_underscore_ && value) {
ignore_underscore_ = value;
auto *parent = dynamic_cast<T *>(parent_);
auto *parent = static_cast<T *>(parent_);
for(const Option_p &opt : parent->options_) {
if(opt.get() == this) {
continue;