如何在我的项目中将*标准库*函数/方法标记为已弃用(或完全禁用)?

Mat*_*lia 10 c++ g++ c++11 deprecation-warning

我试图以某种方式禁用/标记为弃用了可怕的std::string::operator=(char)重载(根据我的经验,仅在错误地将整数分配给字符串时使用,并导致细微且难以跟踪的错误).

我尝试过:

  • 一个带有静态断言的显式特化

    #include <string>
    #include <type_traits>
    
    template<> std::basic_string<char> &std::basic_string<char>::operator=(char c) {
        static_assert(false, "Don't use this!");
    }
    
    Run Code Online (Sandbox Code Playgroud)

    <string>已失败,因为已经显式实例化了std::string

  • [[deprecated]]属性,在各个位置上如上述应用于类似的声明; 我试过的位置似乎没有产生任何合理的结果;
  • =delete,由于与上述类似的原因而失败;
  • 我考虑过使用链接器技巧(在类似的情况下,在同一个项目中,我们setlocale使用--wrap ld链接器选项对运行的使用进行运行时检查),但事实上这是一个模板和内联方法使问题复杂化.

现在问题:

  • 是否有标准方法以某种方式禁用(如将发生=delete)标准库中的任何函数或方法(读取:在库中你不能改变标题中的声明)?
  • 如上所述,但是,而不是禁用,添加警告(如将发生[[deprecated]]);
  • 如果没有标准方法,是否有特定于g ++的东西?
  • 如果没有"通用"(=适用于任何方法,任何类,任何函数,......)解决方案,我们可以应用于这个特定情况(=禁用模板类的方法,甚至可能只是一个具体实例)?

rod*_*igo 4

您可以使用以下编译器/链接器选项:

$ g++ -O0 test.cpp -Wl,--wrap=_ZNSsaSEc
Run Code Online (Sandbox Code Playgroud)

解释:

_ZNSsaSEc是有问题的函数的修饰名称:

$ echo _ZNSsaSEc | c++filt
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(char)
Run Code Online (Sandbox Code Playgroud)

编译-Wl器选项是将选项传递给链接器。

链接--wrap=<symbol>器选项将对给定符号的任何引用转换为替代符号__wrap_<symbol>。由于您(希望)没有定义名为 的函数__wrap__ZNSsaSEc,因此您将得到一个很好的链接器错误:

test.cpp:(.text+0x26): undefined reference to `__wrap__ZNSsaSEc'
Run Code Online (Sandbox Code Playgroud)

并且-O0是禁用优化并阻止编译器内联函数。如果有内联,链接器技巧将不起作用,正如 @SergeBallesta 在评论中指出的那样。

也许有点黑客,但是嘿,它有效!