Can I force a compiler error if certain functions

2020-03-10 05:32发布

问题:

I have v1 and v2 versions of my software. v1 uses the registry to save settings, with lots of calls to GetProfileInt, etc. v2 now uses an sqlite db to save settings.

We are currently developing both branches and are merging new features from v1 to the v2 branch. We currently have to remember to update any registry calls to use the new config db and this has been missed a few times.

What I would like is to throw a compiler error if any of the GetProfile... or WriteProfile... functions are used in v2.

We're using C++ in Visual Studio 2010. If there's nothing built in can I use the output from a script to throw a compiler error somehow?

回答1:

Since this answer is accepted I might as well include the solution the asker actually used:

jacobsee discovered the deprecated pragma

#pragma deprecated(GetProfileInt)

Original answer:

You may be able to declare them as deprecated using __declspec(deprecated). It would look like this:

UINT __declspec(deprecated) WINAPI GetProfileInt(
  __in  LPCTSTR lpAppName,
  __in  LPCTSTR lpKeyName,
  __in  INT nDefault
);

You'll have to do so from a header that is included in every translation unit you care about. Doing so will result in a warning any time a translation unit that includes the deprecated declaration uses that function.

If you want a compiler error and if your project doesn't already treat warnings as errors then you'll have to turn that on, and maybe fix all the warnings you've been ignoring. (These are good practices whether you use this solution or not.)



回答2:

Promoting my comment to an answer:

You can use a macro to redefine them to something that won't compile:

#define GetProfile  HAHA_Nice_try_This_will_not_compile!!!

The catch is that you need to make sure that it isn't (legitimately) called outside your code.
(So you should put the macro after all your includes.)



回答3:

If you have an #include file that is common, you could add something like this to it (with the W or A as appropriate). It would result in, at least, a linker error (compiler warning/error would depend on the flags):

#define GetProfileIntA InvalidFunctionDoNotCallMe

Windows already defines the functions such as GetProfileInt as macros to the A or W versions.



回答4:

The accepted answer is to mark the functions as deprecated, but that doesn't really fit what the question is asking, for two reasons:

  • It only gives a warning, not an error.
  • It will give warnings even if you're using the v1 code.

There's good reasons to want that, but it's not actually what the original question asks for.

Luckily, there's a really easy way to get what the questions asks for. The compiler will always throw an error if the function simply doesn't exist. Just throw the functions in an #ifndef.

#ifndef V2

void GetProfile()
{
  // Get the profile
}

void WriteProfile()
{
  // Write the profile
}

#endif


回答5:

I believe you could #define GetProfileInt(a, b, c) "don't use this"; after #include'ing Windows.h.

Since GetProfileInt is a macro for routing to the proper function, this would result in a macro redefinition. And since char[] can't be assigned to UINT, the compiler error's.

It's a dirty, dirty hack though, I feel like taking a shower for discussing it.