14

我的软件有 v1 和 v2 版本。v1 使用注册表来保存设置,对 GetProfileInt 等进行大量调用。v2 现在使用 sqlite db 来保存设置。

我们目前正在开发两个分支,并将新功能从 v1 合并到 v2 分支。我们目前必须记住更新任何注册表调用以使用新的配置数据库,这已经被错过了几次。

如果在 v2 中使用了任何 GetProfile... 或 WriteProfile... 函数,我想要的是引发编译器错误。

我们在 Visual Studio 2010 中使用 C++。如果没有内置任何内容,我可以使用脚本的输出以某种方式引发编译器错误吗?

4

6 回答 6

12

由于这个答案被接受,我不妨包括提问者实际使用的解决方案:

jacobsee 发现了已弃用的编译指示

#pragma deprecated(GetProfileInt)

原答案:

您可以使用 . 将它们声明为已弃用__declspec(deprecated)。它看起来像这样:

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

您必须从包含在您关心的每个翻译单元中的标题中执行此操作。这样做会在任何时候包含已弃用声明的翻译单元使用该函数时发出警告。

如果您想要编译器错误并且您的项目尚未将警告视为错误,那么您必须打开它,并且可能修复您一直忽略的所有警告。(无论您是否使用此解决方案,这些都是很好的做法。)

于 2012-05-23T20:43:54.400 回答
3

将我的评论推广到答案:

您可以使用宏将它们重新定义为无法编译的内容:

#define GetProfile  HAHA_Nice_try_This_will_not_compile!!!

问题是您需要确保它不会(合法地)在您的代码之外被调用。
(所以你应该把宏放在所有包含之后。)

于 2012-05-23T20:39:51.940 回答
2

接受的答案是将函数标记为已弃用,但这并不真正符合问题的要求,原因有两个:

  • 它只给出警告,而不是错误。
  • 即使您使用的是 v1 代码,它也会发出警告。

有充分的理由想要这样做,但这实际上并不是最初的问题所要求的。

幸运的是,有一种非常简单的方法可以获取问题的要求。如果函数根本不存在,编译器总是会抛出错误。只需将函数放入#ifndef.

#ifndef V2

void GetProfile()
{
  // Get the profile
}

void WriteProfile()
{
  // Write the profile
}

#endif
于 2014-07-09T22:22:58.670 回答
2

如果您可以自由地将函数转换为模板,则可以执行以下操作:

template <typename...>
struct always_false { static constexpr bool value = false; };

template <typename... Ts>
void never_call_me(Ts&&...)
{
  static_assert(always_false<Ts...>::value,
                "You should have never called this function!");
}

这样做的好处是编译错误将是干净的+您可以提供错误消息。在此处找到,请参阅该答案以获取有关为什么有效+为什么always_false需要的更多信息。

于 2020-12-15T10:46:22.397 回答
1

如果您有一个常见的#include 文件,您可以向其中添加类似的内容(使用WA酌情)。它至少会导致链接器错误(编译器警告/错误将取决于标志):

#define GetProfileIntA InvalidFunctionDoNotCallMe

Windows 已经为 A 或 W 版本定义了GetProfileInt宏等功能。

于 2012-05-23T20:38:32.313 回答
0

我相信你可以#define GetProfileInt(a, b, c) "don't use this";#include'ing之后Windows.h

由于GetProfileInt是用于路由到正确功能的宏,因此这将导致宏重新定义。并且由于char[]不能分配给UINT, 编译器error的 .

这是一个肮脏,肮脏的黑客,但我想洗个澡来讨论它。

于 2012-05-23T20:43:56.167 回答