类型安全的字符串参数

Beg*_*ner 5 c++ type-safety

我的库以字符串的形式从消息总线获取信息.这些字符串是需要处理的不同类型实体的标识符.

Currenly方法可能如下所示:

void doWork(const std::string& carModelId,
            const std::string& dealershipId,
            const std::string& invoiceId);

float getPrice(const std::string& carModelId, 
               const std::string& dealershipId);
Run Code Online (Sandbox Code Playgroud)

由于这些不同类型的ID遍布各处,我想确保将正确类型的id传递给方法,而不是使用普通字符串.

我目前的想法是创建一些包裹这些字符串的结构

struct carModel
{
     std::string id;
}
Run Code Online (Sandbox Code Playgroud)

这样这些方法只接受正确的id类型

void doWork(const carModel& carModelId,
            const dealership& dealershipId,
            const invoice& invoiceId);
Run Code Online (Sandbox Code Playgroud)

另一方面,对于常见问题,这似乎是许多额外的样板代码.

问题:获取字符串参数的类型安全性的最佳实践是什么?

Mem*_*eak 4

最佳实践实际上取决于您的软件、环境、IDE、编译器等。你明白了。

在这个特定的场景中,我认为绝对没有问题

struct SomeId {
    std::string id;
}
Run Code Online (Sandbox Code Playgroud)

只要您在整个应用程序中保持所有内容一致即可。您获得的主要优势是,稍后您可以使用其他行为自定义这些结构(获取 id 的使用、在不同数据类型之间进行转换、获取用于调试目的的漂亮打印名称、跟踪应用程序中使用的 Id 等) 。这很好,因为发生的一切对于类的用户来说都是透明的。

另外,这些类型的结构可以自动进行额外的验证(这个 id 是有效的吗?它已经可用了吗?应该是)。您有多少需要这些东西以及它们是否实际上可能取决于您的应用程序的逻辑。

您应该始终保持简单明了,在这种情况下,您实际所做的事情非常适合问题描述。不要让事情变得过于复杂。

然而,有一个建议:在这种情况下远离显式转换运算符等。您应该阻止以下代码的编译。

SomeId id = someOtherIdType;
Run Code Online (Sandbox Code Playgroud)

您可以使用诸如具有operator()operator->用于语法糖之类的技巧,但这就是我所能做到的。

要实现一次并在任何地方使用,您可以将所有内容都放在基类中,如下所示

struct BaseId
{
    std::string id;

    void Do() { }

    //add common behavior to all id classes
    //...
};

struct myId : private BaseId
{
    using BaseId::id;
};
Run Code Online (Sandbox Code Playgroud)

私有继承允许派生类控制要公开的内容和不公开的内容,并防止不同 id 类之间的类型兼容性。

在基类中你可以记录、处理、提供附加方法等等。实现运算符重载也可以在基类中完成。

需要你的身份证吗?我不知道。可能太过分了,也可能不会。但值得考虑这些选择。正如我之前所说,采用适合您的情况的简单方法(即使某些 typedef 可能就足够了,如果没有,结构也会表现良好)。