2014-02-06 41 views
4

在我們的單元測試,我們下面幾行:你能檢測到不可編譯的代碼嗎?

// Should not compile - manually checked 
// auto val = ::Utils::LexicalCast<const char*>(5); 

事實上,如果我取消這個代碼是內LexicalCast未能在static_assert:

static_assert(!std::is_pointer<ToType>::value, "Cannot return pointers from a LexicalCast"); 

,因爲在這種情況下,將不清楚誰擁有記憶。

所以我的問題是,使用任何先進的C++功能(我主要是想SFINAE的,但我不是在它深諳)是可以檢查,如果事情不會編譯由於功能的static_assert 稱爲 ?我不介意在運行時或編譯時檢測,不介意宏等,因爲這些都是測試。

編輯:例如我想是這樣

ASSERT_DOESNT_COMPILE(::Utils::LexicalCast<const char*>(5)); 
+3

簡單情況:提供了定義條件啓用代碼的不同部分。然後有一個'測試驅動程序',它運行帶有不同定義的編譯器,並檢查編譯器在應該時是否失敗。你可能也想看看boost,我認爲它們在庫中有類似的測試(編譯/不編譯) –

+0

從單元測試運行編譯器(exe或lib),並檢查結果? – Jarod42

+1

你能檢測到不可編譯的代碼嗎?是>嘗試編譯它,如果失敗,它是不可編譯的。 – Davidbrcz

回答

1

以下實施例表明,SFINAE不能與static_assert幫助:

#include <type_traits> 

// Fall back version that will always compile 
template<class T> 
void foo(T) {} 

// Specific version using a static_assert that may or may not fire 
template<class T> 
void foo(T*) { 
    static_assert(std::is_same<T, char>::value, "Boo"); 
} 

int main(int argc, char** argv) { 
    // This could call the fall back version, but the static_assert fires anyway 
    foo((int*)0); 
    return 0; 
} 

當與鐺++(3.4)和g ++(4.8.1)編譯時,static_assert火災儘管根據SFINAE它不應該。我的結論是SAFIAE,即Static_Assert失敗是一個錯誤。

+0

你當然可以用'std :: enable_if'替換所有'static_assert'並嘗試構建一些SFINAE構造,但這意味着你禁止使用語言特性,因此幾乎不可取。 我認爲你唯一的選擇是編寫一個腳本,它試圖編譯所有不應該編譯的表達式,並且聲明編譯器返回每個表達式的錯誤。我不認爲這是值得的,但你可以比我更好地判斷。 – gTcV

-2

也許是太明顯了,不過FF你只是在這個特定的(static_assert)感興趣的情況下,你可以簡單地重新#它定義到別的東西:

#include <cassert> 
#include <cstdio> 
using namespace std; 

#define static_assert(flag, msg) { assert(flag); } 

int main() 
{ 
    static_assert(false, "static_assert compile time"); 

    return 0; 
} 
+2

對不起, -1。從語言的角度來看,這是非法的,如果靜態斷言在函數體外部使用(這是可能的,因爲它是一種聲明類型),它根本無法工作。 – Angew

+0

這實際上是一個有趣的選項,所以我給了它一個 - 不幸的是代碼後來不會在static_assert之後編譯,因此即使是運行時失敗(通過在#define中拋出異常)仍然無法編譯 –

+0

我知道這是不正確的(重新定義關鍵字),但例如海灣合作委員會沒有問題。如果靜態斷言在函數體外使用,爲什麼「根本無法工作」?顯然你必須儘早地重新定義它,但是在單元測試中你可以完全控制應該可能的環境。 – proxi