第二個漏洞實施細節漏洞小;如果你從is_arithmetic<int>
或其他任何東西繼承,有人可以通過函數重載進行測試。這可能「起作用」並導致誤報。
這是一個非常小的問題。
如果您的編譯器轉儲基類名稱,您可能會從is_arithmetic
繼承稍微更好的診斷。
您的設計都不合適。相反:
template<class T>
struct some_type_trait:
std::integral_constant<bool,
std::is_arithmetic<T>{}
>
{};
可以擴展,因爲我們可以把任何表達式放在那裏。
正如我前面提到的,錯誤消息具有類型可以是有幫助的,所以我們可以這樣做:
constexpr bool all_of() { return true; }
template<class...Bools>
constexpr bool all_of(bool b0, Bools...bs) {
return b0 && all_of(bs...);
}
template<class T, template<class...>class...Requirements>
struct Requires : std::integral_constant<bool,
Requirements<T>{} &&...
// in C++11/14, something like: all_of(Requirements<T>::value...)
> {};
然後我們得到:
template<class T>
using some_type_trait = Requires<T, std::is_arithmetic>;
如果它未能找到該過載標籤分派,會產生一個錯誤,可能會給你一個線索。
template<class T>
void test(std::true_type passes_test, T t) {
std::cout << t+0 << "\n";
}
template<class T>
void test(T t) {
return test(some_type_trait<T>{}, t);
}
int main() {
test(3);
test("hello");
}
可悲的是,我們沒有簡單的綁定/部分應用程序的當量/在模板元編程鑽營。所以f<.> = is_base_of<X, .>
很難表達清楚。
Live example,我們得到的錯誤信息是: 鏗鏘:
main.cpp:23:10: note: candidate function [with T = const char *] not viable: no known conversion from 'some_type_trait<const char *>' (aka 'Requires<const char *, std::is_arithmetic>') to 'std::true_type' (aka 'integral_constant<bool, true>') for 1st argument
GCC:
main.cpp:28:18: note: cannot convert 'Requires<const char*, std::is_arithmetic>()' (type 'Requires<const char*, std::is_arithmetic>') to type 'std::true_type {aka std::integral_constant<bool, true>}'
至少導致你錯誤(即const char*
不是is_arithmetic
)。
這就是一些高質量的自旋:D – Rerito
FWIW,en.cppreference.com上的「可能的實現」直接繼承了'std :: integral_constant'。遵循這個「風格」,你的例子將繼承自'std :: integral_constant :: value>'。 –
@DanielJour如果我沒有弄錯,從'std :: integral_constant'繼承對類型特徵是強制性的。問題是直接從'std :: integral_constant'直接通過':: type'派生,還是通過類型特徵本身間接派生是更好。也許我不明白你的意見:/ – Morwenn