如何检查像“0”这样的值#定义版本3.1.4“;在编译时? 我正在向我公司的C++项目中添加编译时检查,以确保所有开发机器和构建服务器上的第三方库都是最新的。对于版本3.1.4,大多数库定义如下: #define VERSION_MAJOR 3 #define VERSION_MINOR 1 #define VERSION_BUILD 4

如何检查像“0”这样的值#定义版本3.1.4“;在编译时? 我正在向我公司的C++项目中添加编译时检查,以确保所有开发机器和构建服务器上的第三方库都是最新的。对于版本3.1.4,大多数库定义如下: #define VERSION_MAJOR 3 #define VERSION_MINOR 1 #define VERSION_BUILD 4,c++,c++11,c-preprocessor,C++,C++11,C Preprocessor,使用static\u assert或预处理器指令可以轻松检查这一点 现在我看的是一个第三方库,它定义了一个宏: #define VERSION 3.1.4 如何在编译时验证这样一个宏的值? 使用C++11,我可以使用constexpr字符串比较函数,并将宏字符串化以检查它: constexpr bool static_equal(const char * a, const char * b) { return (*a == *b) && (*a == '\0' ||

使用
static\u assert
或预处理器指令可以轻松检查这一点

现在我看的是一个第三方库,它定义了一个宏:

#define VERSION 3.1.4
如何在编译时验证这样一个宏的值?


使用C++11,我可以使用
constexpr
字符串比较函数,并将宏字符串化以检查它:

constexpr bool static_equal(const char * a, const char * b)
{
    return (*a == *b) && (*a == '\0' || static_equal(a + 1, b + 1));
}

// stringification functions
#define str(x) #x
#define xstr(x) str(x)

static_assert(static_equal(xstr(VERSION), "3.1.4"), "incorrect version of libwhatever");

但是我们在Windows机器上使用Visual Studio 2013,因此我只能使用它支持的C++11的子集。不幸的是,不支持
constepr

您不能在预处理器中使用,但您可以滥用类型特征

VS 2013似乎支持可变模板。尝试使用位于的宏
CSTRING
(您应该能够将
constexpr
替换为
const
,并使代码仍然有效)并执行以下操作:

#定义STRT(x)decltype(CSTRING(x))
静态断言(std::is_same::value,“libwhater的版本不正确”);
编辑:这不起作用。但是,如果编译器编译时没有错误:

extern const char data[]=“abc”;
模板结构x{
静态常量字符c=c;
};
字符buf[(int)x::c];
int main(){return(int)buf;}
然后你可以试试这个:

#include <type_traits>
#define VERSION 1.2.3
#define STR2(x) #x
#define STR(x) STR2(x)

template <char...> struct ststring;

// https://stackoverflow.com/a/15860416/2097780

#define MACRO_GET_1(str, i) \
    (sizeof(str) > (i) ? str[(i)] : 0)

#define MACRO_GET_4(str, i) \
    MACRO_GET_1(str, i+0),  \
    MACRO_GET_1(str, i+1),  \
    MACRO_GET_1(str, i+2),  \
    MACRO_GET_1(str, i+3)

#define MACRO_GET_16(str, i) \
    MACRO_GET_4(str, i+0),   \
    MACRO_GET_4(str, i+4),   \
    MACRO_GET_4(str, i+8),   \
    MACRO_GET_4(str, i+12)

#define MACRO_GET_64(str, i) \
    MACRO_GET_16(str, i+0),  \
    MACRO_GET_16(str, i+16), \
    MACRO_GET_16(str, i+32), \
    MACRO_GET_16(str, i+48)

#define MACRO_GET_STR(str) MACRO_GET_64(str, 0), 0

static_assert(std::is_same<ststring<MACRO_GET_STR(STR(VERSION))>,
                           ststring<MACRO_GET_STR("1.2.3")>>::value,
              "invalid library version");

#包括
#定义版本1.2.3
#定义STR2(x)#x
#定义STR(x)STR2(x)
模板结构ststring;
// https://stackoverflow.com/a/15860416/2097780
#定义宏_GET_1(str,i)\
(sizeof(str)>(i)str[(i)]:0)
#定义宏_GET_4(str,i)\
宏获取1(str,i+0)\
宏_GET_1(str,i+1)\
宏_GET_1(str,i+2)\
宏获取1(str,i+3)
#定义宏_GET_16(str,i)\
宏获取4(str,i+0)\
宏_GET_4(str,i+4)\
宏_GET_4(str,i+8)\
宏获取4(str,i+12)
#定义宏_GET_64(str,i)\
宏获取16(str,i+0)\
宏获取16(str,i+16)\
宏获取16(str,i+32)\
宏获取16(str,i+48)
#定义宏\u GET\u STR(STR)宏\u GET\u 64(STR,0),0
静态断言(std::is_same::value,
“无效库版本”);

如果右键单击项目->属性->生成事件->预生成事件 您将看到一个选项,上面写着“命令行”。你可以在这里给另一个程序打电话

<>你可以用C++或你喜欢的任何语言编写另一个程序,检查你的文件(或者你想要的任何文件),以“y*定义版本3.1.4”。您可以中止构建,并在该程序中添加所需的任何警告

以下是一个教程:

相关阅读:


很长一段时间以来,我一直在尝试使用预处理器命令,但我找不到一种仅使用预处理器命令的方法。

以下是我现在所做的:

#define str(x) #x
#define xstr(x) str(x)

#include xstr(libwhatever.version.is.VERSION.should.be.3.1.4)
除此之外,我还向项目中添加了一个名为
libwhater.version.is.3.1.4.should.be.3.1.4
的空文件。因此,如果版本正确,预处理器将成功包含此文件。否则,它将失败并显示“无法打开”libwhater.version.is.2.7.2.should.be.3.1.4“,没有这样的文件或目录”。最终重要的是,在构建过程中出现一些有意义的消息而导致构建失败

当然,这种方法不是很灵活;例如,我无法检查最小版本或一系列版本。但对我来说,能够检查准确值就足够了


<>这似乎与VisualC++和G++都有作用。不过,我不确定该行为是否完全符合标准。

维护另一个文件可能会更容易,该文件的版本会按照您希望的方式拆分。在预处理器中,恐怕不行。比较只对整数有效,无法拆分令牌3.1.4。它需要某种类型的外部文本处理步骤,或者在运行时进行检查。VS2015 rc已退出,可能支持constexpr。@RSahu:这是第三方库。如果我想向其中添加文件,我必须创建自定义包并强制开发人员使用这些包。这比从原始来源下载要繁琐得多,或者对于Debian及其派生版本,
apt get libwhich dev
。顺便说一句,
static_assert(xstr(VERSION)[0]=='3',“.”
等会因“C2057:预期的常量表达式”而失败@JXH:这也是我对你的建议所得到的。@纸鸟大师:Visual C++ 12(AKA 2013)和G+4.4.2。只有在尝试使用宏而不将其字符串化时,才会出现此类错误。
decltype
将仅检查字符串文字的长度,而不检查字符的长度content@BenVoigt不会的。我以前在代码中使用过这个
decltype
将返回
string
或类似内容。噢,CSTRING宏非常神奇。不,没有constexpr它就不能工作。@BenVoigt即使在它的位置上有
static const
?问题不在于
constexpr
关键字本身,而是没有对任意编译时常量表达式的支持,下标也不会生成编译时常量表达式,因此不能在模板参数中使用。
#define str(x) #x
#define xstr(x) str(x)

#include xstr(libwhatever.version.is.VERSION.should.be.3.1.4)