首页 > 解决方案 > 需要一些关于如何改进这些命令字符串生成器功能的建议

问题描述

我正在为基于行的协议编写 C++ 接口。命令很简单,它们的结构如下:

<cmd> <args>\n

有些命令有固定数量的参数,有些有可变参数。我正在使用 ostringstream 来组装生产线。我编写了两个基类来涵盖带有和不带有可变参数的命令:

class format_command
{
public:
    explicit format_command(std::string const &p_cmd_name)
    {
        m_sstream << p_cmd_name;
    }

    std::string get_string() const;

protected:
    std::ostringstream m_sstream;
};


class format_command_with_args
    : public format_command
{
public:
    explicit format_command_with_args(std::string const &p_cmd_name)
    {
        m_sstream << p_cmd_name;
    }

    template < typename T >
    format_command_with_args& operator << (T const &p_value)
    {
        m_sstream << " " << p_value;
        return *this;
    }
};

然后根据需要派生单独的命令行生成器。让我们以两个示例命令foobar. foo接受固定数量的参数,bar可变参数。

class format_foo
    : public format_command
{
public:
    explicit format_foo(std::string const &p_string, int const p_number)
        : format_command("foo")
    {
        m_sstream << " " << p_string << " " << p_number;
    }
};


class format_bar
    : public format_command_with_args
{
public:
    explicit format_bar(float const p_decimal, char const p_char)
        : format_command("bar")
    {
        m_sstream << " " << p_decimal << " " << p_char;
    }
};

然后我有创建这些类实例的函数。

namespace command
{


format_foo foo(std::string const &p_string, int const p_number)
{
    return format_foo(p_string, p_number);
}


format_bar bar(float const p_decimal, char const p_char)
{
    return format_foo(p_decimal, p_char);
}


}

然后我可以这样做:

std::string command_str = command::foo("hello", 11).get_string();
std::string command_str = (command::bar(1.2f, 'x') << "extra-arg" << "another-arg").get_string();

我通过 command:: 函数添加了这个间接,因为有些命令是这样的:

somecmd <arg1> <arg2> [<arg3> [<varargs>]]

这意味着它们仅在存在特定参数时才具有可变参数。因此,如果第三个参数不存在,我想确保用户不能使用流运算符添加额外的变量参数。在这种情况下,我可以这样做:

class format_somecmd
    : public format_command
{
public:
    explicit format_somecmd(std::string const &p_arg1, std::string const &p_arg2)
        : format_somecmd("bar")
    {
        m_sstream << " " << p_arg1 << " " << p_arg2;
    }
};
class format_somecmd_with_args
    : public format_command_with_args
{
public:
    explicit format_somecmd_with_args(std::string const &p_arg1, std::string const &p_arg2, std::string const &p_arg3)
        : format_somecmd("bar")
    {
        m_sstream << " " << p_arg1 << " " << p_arg2 << " " << p_arg3;
    }
};

namespace command
{

format_somecmd somecmd(std::string const &p_arg1, std::string const &p_arg2)
{
    return format_somecmd(p_arg1, p_arg2);
}

format_somecmd_with_args somecmd(std::string const &p_arg1, std::string const &p_arg2, std::string const &p_arg3)
{
    return format_somecmd_with_args(p_arg1, p_arg2, p_arg3);
}

这样,我可以这样做:

std::string command_str = command::somecmd("hello", "world").get_string();
std::string command_str = (command::somecmd("hello", "world", "test") << "extra-arg" << "another-arg").get_string();

这在编译时失败(这是故意的,因为这将是一个无效的命令):

std::string command_str = (command::somecmd("hello", "world") << "extra-arg" << "another-arg").get_string();

到目前为止,这运作良好。困扰我的部分是.get_string(). 我考虑过使用operator std::string(),但这似乎是一罐蠕虫。

关于如何改进它的任何建议,特别是关于get_string()

标签: c++

解决方案


推荐阅读