我想確保一個static_assert在單元測試中的正常工作。也就是說,如果我有一個在單元測試中驗證static_assert
class MyClass {static_assert(my_type_trait<T>::value, "error"); };
然後在單元測試MyClass<TypeWithTrait> myClass;
應該「通行證」和MyClass<TypeWithoutTrait> myClass;
應該「失敗」。
是否有可能做到這樣的事情?
我想確保一個static_assert在單元測試中的正常工作。也就是說,如果我有一個在單元測試中驗證static_assert
class MyClass {static_assert(my_type_trait<T>::value, "error"); };
然後在單元測試MyClass<TypeWithTrait> myClass;
應該「通行證」和MyClass<TypeWithoutTrait> myClass;
應該「失敗」。
是否有可能做到這樣的事情?
如果你想檢查某些東西無法編譯,你必須測試代碼的外部。只要寫一個簡單的文件,如:
#include "MyClass.h"
int main() {
MyClass<%T%> m;
}
,寫一個單元測試,編譯該文件與%T%
不同的值。驗證編譯是否按預期成功,或者按照預期在故障文本中失敗了static_assert
。
巴里的建議是一種可能性,但如果你有很多事情要測試,你需要創建許多小文件。更重要的是,這些文件可能因爲其他原因而無法編譯,而不是您期望的,從而給您的測試通過一個錯誤的感覺。
另一種方法是,而不是使用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_trait
的true
分支中觸發軟SFINAE錯誤,我實際上必須默認構建traits類的一個實例。如果你編寫你的traits類,所以它們不是默認的可構造的,這是行不通的。但總的來說,你不會那樣寫。會好奇,看看有沒有更好的方法去做
所以我想我試圖檢查的一個案例是有人沒有從類中刪除static_assert。所以,如果我明白你說的正確,這將有助於在我只是想檢查是否static_assert會失敗的情況下,但如果我試圖檢查是否static_assert實際存在,並失敗它應該我應該不要認爲這有幫助。 –
是的,它是你試過嗎? – 101010
@ 101010是的,我只是得到一個編譯器錯誤。 –
@DavidDoria:那麼?這正是靜態斷言的用途。測試通過,如果這是預期的,失敗如果不是。 – Mat