2016-02-08 67 views
4

我想確保一個static_assert在單元測試中的正常工作。也就是說,如果我有一個在單元測試中驗證static_assert

class MyClass {static_assert(my_type_trait<T>::value, "error"); }; 

然後在單元測試MyClass<TypeWithTrait> myClass;應該「通行證」和MyClass<TypeWithoutTrait> myClass;應該「失敗」。

是否有可能做到這樣的事情?

+0

是的,它是你試過嗎? – 101010

+0

@ 101010是的,我只是得到一個編譯器錯誤。 –

+0

@DavidDoria:那麼?這正是靜態斷言的用途。測試通過,如果這是預期的,失敗如果不是。 – Mat

回答

3

如果你想檢查某些東西無法編譯,你必須測試代碼的外部。只要寫一個簡單的文件,如:

#include "MyClass.h" 

int main() { 
    MyClass<%T%> m; 
} 

,寫一個單元測試,編譯該文件與%T%不同的值。驗證編譯是否按預期成功,或者按照預期在故障文本中失敗了static_assert

-1

巴里的建議是一種可能性,但如果你有很多事情要測試,你需要創建許多小文件。更重要的是,這些文件可能因爲其他原因而無法編譯,而不是您期望的,從而給您的測試通過一個錯誤的感覺。

另一種方法是,而不是使用static_assert,您使用某種SFINAE來檢測是否有效。對於traits類,這是一個有點棘手,但你可以這樣做:

template <class T> 
using void_t = void; 

template <class T> 
struct foo; 

template <> 
struct foo <double> {}; 

template <class T, class = void> 
struct has_foo_trait : std::false_type {}; 

template <class T> 
struct has_foo_trait<T, void_t<decltype(foo<T>{})>> : std::true_type {}; 

int main(int, char**) { 
    std::cerr << has_foo_trait<int>::value; 
    std::cerr << has_foo_trait<double>::value; 
    return 0; 
} 

此打印出01。所以,現在,不是直接從static_assert ing得到一個硬性故障,你可以在編譯時計算trait存在的值,然後static_assert得到你期望的值。

請注意,特徵類是棘手的原因是因爲特徵被聲明爲通用模板,只是未定義。因此,在void_t中直接使用類型的「常規」元編程功能不起作用。爲了在has_foo_traittrue分支中觸發軟SFINAE錯誤,我實際上必須默認構建traits類的一個實例。如果你編寫你的traits類,所以它們不是默認的可構造的,這是行不通的。但總的來說,你不會那樣寫。會好奇,看看有沒有更好的方法去做

+0

所以我想我試圖檢查的一個案例是有人沒有從類中刪除static_assert。所以,如果我明白你說的正確,這將有助於在我只是想檢查是否static_assert會失敗的情況下,但如果我試圖檢查是否static_assert實際存在,並失敗它應該我應該不要認爲這有幫助。 –