簡體   English   中英

如何在編譯時檢查像“#define VERSION 3.1.4”這樣的值?

[英]How to check a value like “#define VERSION 3.1.4” at compile time?

我正在為我公司的C ++項目添加編譯時檢查,以確保所有開發機器和構建服務器上的第三方庫都是最新的。 大多數庫定義類似於以下內容的版本,例如版本3.1.4:

#define VERSION_MAJOR 3
#define VERSION_MINOR 1
#define VERSION_BUILD 4

使用static_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子集。 不幸的是, constexpr不受支持。

這是我現在正在做的事情:

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

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

與此同時,我將一個名為libwhatever.version.is.3.1.4.should.be.3.1.4的空文件添加到項目中。 因此,如果版本正確,預處理器將成功包含此文件。 否則,它將失敗,“無法打開'libwhatever.version.is.2.7.2.should.be.3.1.4',沒有這樣的文件或目錄”。 並且使用有意義的消息來構建失敗是最重要的。

當然這種方法不夠靈活; 例如,我無法檢查最小版本或一系列版本。 但對我來說,能夠檢查確切的值就足夠了。

這似乎適用於Visual C ++以及g ++。 不過,我不確定這種行為是否完全按照標准定義。

你不能在預處理器中,但你可以濫用類型特征!

VS 2013似乎支持可變參數模板。 嘗試在https://stackoverflow.com/a/15912824/2097780上使用宏CSTRING (您應該能夠用const替換constexpr並使代碼仍然有效)並執行以下操作:

#define STRT(x) decltype(CSTRING(x))
static_assert(std::is_same<STRT(VERSION), STRT("3.1.4")>::value, "incorrect version of libwhatever");

編輯:這不起作用。 但是,如果您的編譯器編譯它沒有錯誤:

extern const char data[] = "abc";
template <char C> struct x {
    static const char c = C;
};
char buf[(int)x<"ABC123"[0]>::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");

如果右鍵單擊項目 - >屬性 - >構建事件 - >預構建事件您將看到一個顯示“命令行”的選項。 你可以在這里撥打另一個電話。

您可以用C ++或您喜歡的任何語言編寫另一個程序來檢查您的文件(或任何數量的文件)以查找“#define VERSION 3.1.4”。 您可以中止構建並在該程序中添加所需的任何警告。

這是一個教程: https//dillieodigital.wordpress.com/2012/11/27/quick-tip-aborting-builds-in-visual-studio-based-on-file-contents/

相關閱讀: https//msdn.microsoft.com/en-us/library/e85wte0k.aspx

我試過很長時間搞亂預處理程序命令,我找不到使用預處理程序命令的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM