Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mark a *standard library* function/method as deprecated (or disabled altogether) in my project?

I'm trying to somehow disable/mark as deprecated the hideous std::string::operator=(char) overload (which in my experience is used only when mistakingly assigning an integer to a string, and causes subtle and difficult to track bugs).

I tried with:

  • an explicit specialization with a static assert in it

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

    which fails as <string> already does an explicit instantiation of std::string

  • the [[deprecated]] attribute, applied to a similar declaration as above in various positions; no position I tried seemed to yield any reasonable result;
  • =delete, which fails for reasons similar to above;
  • I thought about using linker tricks (in a similar vein, in the same project we have runtime checks on stray setlocale usages using the --wrap ld linker option), but the fact that this is a template and inline method complicates the matter.

Now to the questions:

  • is there a standard method to somehow disable (as would happen with =delete) any function or method in the standard library (read: in a library where you cannot alter the declarations in the headers)?
  • as above, but, instead of disable, add a warning (as would happen with [[deprecated]]);
  • failing the standard method, is there something g++-specific?
  • if there's no "general" (=applicable to any method, any class, any function, ...) solution, is there something that we could apply to this specific case (=disable a method of a template class, possibly even just a specific instantiation)?
like image 965
Matteo Italia Avatar asked Nov 18 '15 10:11

Matteo Italia


Video Answer


1 Answers

You can use the following compiler/linker option:

$ g++ -O0 test.cpp -Wl,--wrap=_ZNSsaSEc

Explanation:

The _ZNSsaSEc is the decorated name of your offending function:

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

The -Wl compiler option is to pass options to the linker.

And the --wrap=<symbol> linker option transforms any reference to the given symbol to the alternative __wrap_<symbol>. And since you are (hopefully) not defining a function named __wrap__ZNSsaSEc, you will get a nice linker error:

test.cpp:(.text+0x26): undefined reference to `__wrap__ZNSsaSEc'

And -O0 is to disable optimizations and prevent the compiler from inlining the function. The linker trick will not work if there is inlining, as @SergeBallesta pointed out in the comment.

Maybe a bit of a hack, but hey, it works!

like image 148
rodrigo Avatar answered Oct 16 '22 06:10

rodrigo