C++ 在编译器之前检测未声明的标识符

C++ 在编译器之前检测未声明的标识符,c++,c++11,C++,C++11,我正在开发一个多平台的代码库,在其中一个平台上,sprintf_s不可用,但snprintf确实存在,所以在这种情况下,解决方案是有一行代码 #define sprintf_s snprintf 但是,我想自动恢复这个,或者抛出一个编译时错误,以便在平台实现sprintf_时手动执行 我在这里发现了多个问题来检测一个类是否定义了成员函数或流操作符是否存在重载,但对于像sprintf_s这样的函数却没有 我不想使用任何实验性的东西,但如果std::experimental::is_是唯一的解决方

我正在开发一个多平台的代码库,在其中一个平台上,sprintf_s不可用,但snprintf确实存在,所以在这种情况下,解决方案是有一行代码

#define sprintf_s snprintf
但是,我想自动恢复这个,或者抛出一个编译时错误,以便在平台实现sprintf_时手动执行

我在这里发现了多个问题来检测一个类是否定义了成员函数或流操作符是否存在重载,但对于像sprintf_s这样的函数却没有

我不想使用任何实验性的东西,但如果std::experimental::is_是唯一的解决方案,那就这样吧

理想的解决方案看起来像

if !sprintf exists
    #define sprintf_s snprintf
但类似于以下内容也可以接受

static_assert(!sprintf_s_exists, "sprintf_s is now defined");

提供sprintf_的实现应该在中定义宏u STDC_LIB_EXT1_u。在包含标头之前,您还可以将uu STDC_WANT_LIB_EXT1_uuuu定义为1

您还可以检查您确定支持它的实现,例如具有最小版本号的MSVC,并仅对这些实现有条件地启用它


更一般的做法是auticonf传统上所做的:尝试编译一个调用您正在测试的函数的小程序,并检查返回值。如果程序按预期编译和运行,脚本会在配置文件中添加一个宏,如HAS_SPRINTF_S,然后程序可以进行测试。

这种问题通常并不少见。在生成特定于平台的make或ninja文件时,许多系统在构建的配置阶段解决了这个问题。在那里,您通常会为构建系统生成器提供一个小功能测试应用程序,该应用程序要么编译良好,要么编译失败,并且您通常可以通过让构建系统生成器根据这两种结果定义所需的编译器宏来为构建系统的逻辑奠定基础


在CMake中,与上面类似的东西被称为

,编译器通常定义一组宏来区分编译到的平台。您可以将它们与ifdef和ENDIF一起使用,如果找不到编译器宏,则需要使用CMAKE或您拥有的任何生成系统来测试功能并相应地设置宏。@Yksisarvinen这并不能真正解决我的问题。我已经可以基于平台有条件地定义函数了整个文件只存在于我的目标平台上,但这并不能解决该平台内sdk的变化,我不想每次升级时都检查它,如果我能让它自动告诉我的话。我在上一个项目中一直面临这个问题,操作系统功能将在操作系统之间不断变化。因此,用于将自定义测试文件编译为cmake feature test,并相应地设置宏。这让我的生活轻松了一点。