代码之家  ›  专栏  ›  技术社区  ›  Miral

在使用复制构造函数和赋值时生成警告

  •  3
  • Miral  · 技术社区  · 7 年前

    有没有一种方法可以让编译器(这里特别是MSVC 2017,但其他编译器也可能很有趣)在特定类的复制构造函数和复制分配运算符所在的位置发出警告? 习惯于 (以一种可以在每个呼叫站点明确抑制的方式,即使是间接抑制)?

    This question 询问如何产生编译错误,现在用C++ 11删除方法很容易,但我希望代码仍然编译,只输出警告。

    原因是我有一个类,它当前在整个代码库中被大量复制。我不想阻止它被复制(其中一些是必需的),但我想检查每个位置,以确定是否应该将其更改为移动,还是通过引用传递。

    让编译器临时标记构造函数的用法作为警告似乎是一种很好的方法。

    我尝试添加如下内容:

    __declspec(deprecated) MyType(MyType const&) = default;
    

    但这不起作用;显然 = default 赢得任何其他修改者。

    我做了同样的事情,但是完全实现了这个方法,并且 几乎 工作——它在每个呼叫站点生成c4996,我可以查看这些内容,或者更改它们,或者点击:

    #pragma warning(suppress:4996)
    

    如果我很高兴这是必需的副本。(我最终计划删除这些内容,以及对构造函数的贬低——这只是内务管理,用于跟踪我尚未处理的内容。)

    不幸的是,有些情况我不能用这种方式抑制,例如:

    std::vector<MyType> list;
    list.push_back(type);
    list.emplace_back(MyType{ type });
    

    这些行中的每一行都会引发警告(第一行是因为它是具有常规复制构造函数的类中的字段声明),但这里只能直接禁止第三行。前两个在 <vector> 并且似乎不受这行代码的警告禁止(或禁用)的影响。

    有什么方法可以解决这个问题,还是有其他方法来做我想做的事情?

    2 回复  |  直到 7 年前
        1
  •  0
  •   Miral    7 年前

    它看起来并不完全优雅,但我可以使用以下策略抑制最为嘈杂的情况(头文件中类的向量成员)。其余的案件在那之后相当突出,不需要单独加以压制;它们可以被修复或忽略。

    1. 添加不推荐使用的复制和不推荐使用的移动构造函数和分配:

      __declspec(deprecated) MyType(MyType const& o) { /* actual impl */ }
      __declspec(deprecated) MyType& operator=(MyType const& o) { /* impl */ return *this; }
      MyType(MyType&&) = default;
      MyType& operator=(MyType&&) = default;
      
    2. 同时添加一个不推荐使用的转发类型占位符:

      struct SuppressMyType : MyType
      {
          using MyType::MyType;
      #pragma warning(disable:4996)
          SuppressMyType(SuppressMyType const& o) : MyType(o) {}
          SuppressMyType& operator=(SuppressMyType const& o)
              { MyType::operator=(static_cast<MyType const&>(o)); return *this; }
          SuppressMyType(MyType const& o) : MyType(o) {}
          operator MyType() const { return *this; }
      #pragma warning(default:4996)
      };
      
    3. 更改副本的使用位置 SuppressMyType 而不是 MyType .

    4. 修理其他地方,直到警告消失。

    5. 全部替换 抑制型 回到 MyType ,然后删除1中添加的代码。

    有点费解,但它做到了。

        2
  •  0
  •   Miral    7 年前

    换一种方式做之后再多想想,换一种方式做可能更好(也更容易):

    1. 全部大批量替换 MyType WarnMyType (实际定义除外 MyType 当然。
    2. 添加 华美型 不推荐使用的构造函数:

      struct WarnMyType : MyType
      {
          using MyType::MyType;
          __declspec(deprecated) WarnMyType(WarnMyType const& o) : MyType(o) {}
          __declspec(deprecated) WarnMyType& operator=(WarnMyType const& o)
              { MyType::operator=(static_cast<MyType const&>(o)); return *this; }
          WarnMyType(WarnMyType&&) = default;
          WarnMyType& operator=(WarnMyType&&) = default;
      };
      
    3. 逐渐改变 华美型 回到 MyType 当他们被检查时。

    4. 去除 华美型 .
    5. 大量更换剩余的 华美型 回到 MyType (因为3只会找到复印件的地方)。

    如果这些工具能够像在命名方法中那样容易地找到构造函数/运算符的用法,那就太好了…