refactor(cli): improve option handling with defaults and protected inheritance

Update OptionUtils to include name placeholders for default values, switch cli
classes to protected inheritance, and use at() for safer option retrieval.
This commit is contained in:
Ваше Имя
2025-10-05 14:13:52 +04:00
parent 75563091c1
commit 20640e766e
7 changed files with 32 additions and 31 deletions
+8 -9
View File
@@ -1,4 +1,5 @@
#include "echo_client_cli.hpp"
#include <boost/program_options/value_semantic.hpp>
EchoClientCli::EchoClientCli()
: CliBase("Echo Client Options")
@@ -12,24 +13,22 @@ void EchoClientCli::setupOptions()
{
// clang-format off
desc_.add_options()
("help,h", "Show help")
("host,H", withDefault(host_), "Server host (IP or DNS name)")
("port,p", withDefault(port_), "Server port")
("message,m", withDefault(message_), "Message to send");
("help,h", "Show help")
("host,H", withDefault(host_, "<HOST>"), "Server host (IP or DNS)")
("port,p", withDefault(port_, "<PORT>"), "Server port")
("message,m", withDefault(message_, "<TEXT>"), "Message to send");
// clang-format on
}
std::string EchoClientCli::getHost() const
{
return vm_["host"].as<std::string>();
return vm_.at("host").as<std::string>();
}
int EchoClientCli::getPort() const
{
return vm_["port"].as<int>();
return vm_.at("port").as<int>();
}
std::string EchoClientCli::getMessage() const
{
return vm_["message"].as<std::string>();
return vm_.at("message").as<std::string>();
}
+2 -1
View File
@@ -4,7 +4,7 @@
#include "option_utils.hpp"
#include <string>
class EchoClientCli : public CliBase, public OptionUtils
class EchoClientCli : public CliBase, protected OptionUtils
{
public:
EchoClientCli();
@@ -17,6 +17,7 @@ class EchoClientCli : public CliBase, public OptionUtils
void setupOptions() override;
private:
// defaults (used only to show defaults in help via withDefault)
std::string host_;
int port_;
std::string message_;
+8 -2
View File
@@ -4,11 +4,17 @@
class OptionUtils
{
public:
template <typename T>
using OptionValue = boost::program_options::typed_value<T> *;
template <typename T>
static OptionValue<T>
withDefault(const T &value, const char *name = nullptr);
protected:
OptionUtils() = default;
~OptionUtils() = default;
template <typename T> static auto withDefault(T value);
};
#include "option_utils.tpp"
+8 -3
View File
@@ -1,8 +1,13 @@
#pragma once
#include "option_utils.hpp"
template <typename T> auto OptionUtils::withDefault(T value)
template <typename T>
OptionUtils::OptionValue<T>
OptionUtils::withDefault(const T &value, const char *name)
{
return boost::program_options::value<T>()->default_value(value);
auto v = boost::program_options::value<T>()->default_value(value);
if (name) {
v->value_name(name); // Optional
}
return v;
}
-9
View File
@@ -1,9 +0,0 @@
#pragma once
class Server
{
public:
virtual ~Server() = default;
virtual void start() = 0;
virtual void stop() = 0;
};
+5 -6
View File
@@ -11,18 +11,17 @@ void EchoServerCli::setupOptions()
{
// clang-format off
desc_.add_options()
("help,h", "Show help")
("port,p", withDefault(port_), "Port to listen on")
("address,a", withDefault(address_), "Bind address (e.g. 0.0.0.0 or 127.0.0.1)");
("help,h", "Show help")
("port,p", withDefault(port_, "<PORT>"), "Port to listen on")
("address,a", withDefault(address_, "<ADDRESS>"), "Bind address (e.g. 0.0.0.0)");
// clang-format on
}
int EchoServerCli::getPort() const
{
return vm_["port"].as<int>();
return vm_.at("port").as<int>();
}
std::string EchoServerCli::getAddress() const
{
return vm_["address"].as<std::string>();
return vm_.at("address").as<std::string>();
}
+1 -1
View File
@@ -4,7 +4,7 @@
#include "option_utils.hpp"
#include <string>
class EchoServerCli : public CliBase, public OptionUtils
class EchoServerCli : public CliBase, protected OptionUtils
{
public:
EchoServerCli();