【问题标题】:Enforce type safety in C++ without using extra classes在 C++ 中强制类型安全而不使用额外的类
【发布时间】:2017-03-29 10:49:15
【问题描述】:

我对类型安全有点熟悉,并且之前在接收多个相同类型(bool)参数的方法中成功使用它以避免混淆。例如:

// Old version of the method
void sendPackage(bool sendImmediately, bool dividePacket);

// Type safe version
enum SendImmediatelyPreference
{
    SEND_IMMEDIATELY,
    DO_NOT_SEND_IMMEDIATELY
};

enum PacketDivisionPreference
{
    DIVIDE_PACKET,
    DO_NOT_DIVIDE_PACKET
};

void sendPackage(
    SendImmediateltPreference immediatePref,
    PacketDivisionPreference divisionPref);

所以神秘的sendPackage(true, false) 变成了sendPackage(SEND_IMMEDIATELY, DO_NOT_DIVIDE_PACKET)

问题是这只是bool 的一个选项。我有一个接受多个std::vector<std::string> 的方法,我想尽量减少用户以错误顺序输入参数的可能性。

我可以考虑创建包含 std::vector<std::string> 的不同类,并覆盖大量 std::vector 方法或公开内部向量。

有没有更简单的方法,某种 typedef 可以强制类型安全?使用boost 就可以了。

【问题讨论】:

  • 我会看看this question。不幸的是,C++ 没有强类型的 typedef,但您可以尝试解决这个问题。
  • 我不知道如何在不使用不同类型的情况下获得类型安全。我想你可以像这样使用std::pairstruct type1{}; struct type2{}; std::pair<type1, std::vector<std::string>> v1; std::pair<type2, std::vector<std::string>> v2;
  • 感谢您的回答,@BartekBanachewicz 和 @RichardCritten。 BOOST_STRONG_TYPEDEF 似乎是我正在寻找的东西,但很高兴知道它的局限性:)

标签: c++ c++11 boost type-safety


【解决方案1】:

使用命名参数的替代方法怎么样?在here 中描述的 C++ 中有几种方法可以解决这个问题。使用元组的标记方法看起来很合理。还有boost parameter

这并不能提供强大的类型安全性,但您可能会争辩说,用户调用错误的构造函数以使其成为类型安全的对象的可能性与他们在调用您的函数时使用错误的标记一样可能。如果在整个应用程序中使用这些类型而不是仅为一个特定函数定义,则这种情况不太可能发生。

另请参阅关于 boost strong typedef vs parameter 的讨论here

【讨论】:

    【解决方案2】:

    不确定我是否理解正确,但也许这会有所帮助:

    enum SendImmediatelyPreference : bool  // allows only 2 options:
    {
      DO_NOT_SEND_IMMEDIATELY,  // false
      SEND_IMMEDIATELY          // true
    }
    

    【讨论】:

    • 不,抱歉,这不能回答我的问题(这与向量有关,尽管理想情况下它会是一个通用答案)
    【解决方案3】:

    如何创建一个从 std::vector 继承(公共)的类以进行强类型检查。好处是你只需要重写构造函数..

    您还可以在 std::unordered_map> 中重新组合参数,以将参数实现为 dict(如在 python 或 javascript 中)

    【讨论】:

    • 我想到了这种可能,但是我不喜欢扩展STL(虽然也许我应该更灵活一些)。
    【解决方案4】:

    BOOST_STRONG_TYPEDEF 正是一个 typedef,它强制类型安全。

    但是,this answer 提供了一些关于仅将这种强 typedef 用于函数的警告,并认为应该在整个代码中使用这些类型以防止不必要的强制转换。

    【讨论】:

      【解决方案5】:

      我喜欢将参数捆绑在配置类或结构中。例如:

      struct SendOptions
      {
          bool send_immediately = false;
          bool divide_packet = false;
          // ...
      };
      
      void sendPackage(SendOptions options);
      

      这有一个额外的好处,额外的选项可以在以后添加而无需更改sendPackage(SendOptions)的接口。

      这不会提高类型安全性,但它确实有助于防止错误(尤其是在有很多参数的情况下),这可能是您想要实现的目标。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-26
        • 1970-01-01
        • 1970-01-01
        • 2015-12-19
        • 1970-01-01
        • 1970-01-01
        • 2015-06-20
        相关资源
        最近更新 更多