Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I deprecate a C++ header?

Tags:

c++

deprecated

I would like to deprecate a C++ header so that if someone includes it in their code, the compiler issues a warning.

I know that I can deprecate individual symbols, for example, using C++14 [[deprecated]], but is there a similar thing for headers? Maybe some clever trick?

Note that I want the compiler to issue a warning even if the user doesn't use anything from the header.

like image 215
herr_shamanskiy Avatar asked Jul 08 '21 18:07

herr_shamanskiy


People also ask

Does C need a header file?

The creation of header files are needed generally while writing large C programs so that the modules can share the function definitions, prototypes etc. Function and type declarations, global variables, structure declarations and in some cases, inline functions; definitions which need to be centralized in one file.

Why does C have headers?

Header files serve two purposes. System header files declare the interfaces to parts of the operating system. You include them in your program to supply the definitions and declarations you need to invoke system calls and libraries.

Where are header files stored C?

These are the directories that gcc looks in by default for the specified header files ( given that the header files are included in chevrons <>); 1. /usr/local/include/ --used for 3rd party header files. 2. /usr/include/ -- used for system header files.

How to use header file in C program?

You request to use a header file in your program by including it with the C preprocessing directive #include, like you have seen inclusion of stdio.h header file, which comes along with your compiler.

Which headers are subject to deprecation?

In those cases, only the header name is subject to deprecation, not the contents. Note: you can deduce which headers are subject to this kind of deprecation by matching their names in the document you link to. Obviously, this only works for standard headers.

What is the best way to declare a function deprecated?

The Microsoft-specific __declspec (deprecated) declaration modifier is also a better choice in many cases than the deprecated pragma. The [ [deprecated]] attribute and __declspec (deprecated) modifier allow you to specify deprecated status for particular forms of overloaded functions.

What does [DEP deprecated]] mean in C++?

[ [deprecated ("Replaced by bar, which has an improved interface")]] void foo (int); The message must be a string literal. For further details, see “Marking as deprecated in C++14”. Can you use [ [deprecated]] in a macro?


Video Answer


5 Answers

Here is a possible (albeit perhaps not too elegant) solution.

Insert in the header a code like that

// badheader.hpp
namespace {
[[deprecated("This header is deprecated")]]
constexpr static int badheader_hpp_is_deprecated = 0;
constexpr static int please_dont_use_badheader_hpp = badheader_hpp_is_deprecated;
}

This creates a deprecated variable badheader_hpp_is_deprecated. The initialization of please_dont_use_badheader_hpp triggers the deprecated warning. Notice that I put both variables inside an anonymous namespace, to avoid possible name conflicts. Still, as noted in the comment, a name clash could still happen if, in the same compilation unit, a variable with the same name is declared inside the anonymous namespace. For this reason, as suggested in the comments, variables in the code above have a descriptive name, rendering name clash high improbable.

like image 63
francesco Avatar answered Oct 19 '22 09:10

francesco


A non-standard, but fairly portable solution:

#pragma message("Header `foo.h` is deprecated!")

This is accepted by GCC, Clang, and MSVC. GCC and Clang also accept the form without ( ).

This is not necessarily a "warning", but should be good enough.

like image 21
HolyBlackCat Avatar answered Oct 19 '22 09:10

HolyBlackCat


I suggest surrounding your namespace with a namespace with the same name and using it from within the enclosing namespace.

#pragma once

namespace your_namespace {
    namespace [[deprecated]] your_namespace {
        // old stuff
    }
    using namespace your_namespace;
}

This shouldn't taint your global namespace with anything from your_namespace and still give the warning if you include the header. The old stuff will still be accessible via your_namespace:: as before.

Since this is an ABI breaking change, I recommend stepping the major version of the library too if you didn't already when deprecating the header.

like image 16
Ted Lyngmo Avatar answered Oct 19 '22 07:10

Ted Lyngmo


This one is shamelessly copied from the range-v3 library:

#ifdef __GNUC__
#define RANGES_PRAGMA(X) _Pragma(#X)
#define RANGES_DEPRECATED_HEADER(MSG) RANGES_PRAGMA(GCC warning MSG)
#elif defined(_MSC_VER)
#define RANGES_STRINGIZE_(MSG) #MSG
#define RANGES_STRINGIZE(MSG) RANGES_STRINGIZE_(MSG)
#define RANGES_DEPRECATED_HEADER(MSG) \
    __pragma(message(__FILE__ "(" RANGES_STRINGIZE(__LINE__) ") : Warning: " MSG))
#endif

RANGES_DEPRECATED_HEADER("Yikes! A deprecated header!")

Try it with Compiler Explorer.

like image 12
ComicSansMS Avatar answered Oct 19 '22 09:10

ComicSansMS


If your header has a namespace, you could use the [[deprecated]] on it I guess? But this doesn't work on anonymous namespaces. And the user has to use something from the headspace for it to work.

If you can put the header in a namespace, then all you have to do is have a using statement that will trigger the warning. This could be also a good idea to isolate those functions, and making sure users have more difficulty using them if that's an objective.

namespace [[deprecated]] N {
    struct S {

    };
}

using N::S;

But if you can't afford the namespace, depending on the number of elements, you probably don't want to use a using on all of them. Maybe that could be a case for legitimately having a using namespace N;, but I'm not sure.

After some research, you could use #pragma message "Message" to possibly also achieve what you seem to be wanting. See this answer

godbolt

like image 6
ShadowMitia Avatar answered Oct 19 '22 08:10

ShadowMitia