在C++ 11我發現最短,最一般的解決方案是這一個:
#include <type_traits>
template<class T, class = decltype(std::declval<T>() < std::declval<T>())>
std::true_type supports_less_than_test(const T&);
std::false_type supports_less_than_test(...);
template<class T> using supports_less_than = decltype(supports_less_than_test(std::declval<T>()));
#include<iostream>
struct random_type{};
int main(){
std::cout << supports_less_than<double>::value << std::endl; // prints '1'
std::cout << supports_less_than<int>::value << std::endl; // prints '1'
std::cout << supports_less_than<random_type>::value << std::endl; // prints '0'
}
作品與g++ 4.8.1
和clang++ 3.3
任意操作者A更通用的解決方案(UPDATE 2014)
有一個更通用的解決方案,利用所有buil t-in操作符也可以通過STD操作符包裝(如std::less
(二進制)或std::negate
(一元))訪問(並且可以專用)。
template<class F, class... T, typename = decltype(std::declval<F>()(std::declval<T>()...))>
std::true_type supports_test(const F&, const T&...);
std::false_type supports_test(...);
template<class> struct supports;
template<class F, class... T> struct supports<F(T...)>
: decltype(supports_test(std::declval<F>(), std::declval<T>()...)){};
這可以以相當普遍的方式來使用,特別是在C++ 14,其中型扣被延遲給操作者包裝呼叫(「透明運營商」)。
對於二進制運算符它可以用作:
#include<iostream>
struct random_type{};
int main(){
std::cout << supports<std::less<>(double, double)>::value << std::endl; // '1'
std::cout << supports<std::less<>(int, int)>::value << std::endl; // '1'
std::cout << supports<std::less<>(random_type, random_type)>::value << std::endl; // '0'
}
對於一元運算符:
#include<iostream>
struct random_type{};
int main(){
std::cout << supports<std::negate<>(double)>::value << std::endl; // '1'
std::cout << supports<std::negate<>(int)>::value << std::endl; // '1'
std::cout << supports<std::negate<>(random_type)>::value << std::endl; // '0'
}
(用C++ 11標準庫是有點複雜,因爲沒有失敗即使沒有爲random_type
定義操作,也可以實現decltype(std::less<random_type>()(...))
,但是可以在C++ 11中實現手動透明運算符,這些運算符在C++ 14中是標準的)
語法非常流暢。我希望標準中採用這樣的東西。
兩個擴展:
1)它的工作原理,以檢測原始功能的應用:
struct random_type{};
random_type fun(random_type x){return x;}
int main(){
std::cout << supports<decltype(&fun)(double)>::value << std::endl; // '0'
std::cout << supports<decltype(&fun)(int)>::value << std::endl; // '0'
std::cout << supports<decltype(&fun)(random_type)>::value << std::endl; // '1'
}
2)它可以另外地檢測如果結果是可兌換/可比到一定類型,在這種情況下,支持double < double
,但由於結果不是指定的,因此將返回編譯時false。
std::cout << supports<std::equal_to<>(std::result_of<std::less<>(double, double)>::type, random_type)>::value << std::endl; // '0'
注:我只是試圖編譯C++ 14的代碼http://melpon.org/wandbox/並沒有奏效。我認爲在該實現中(clang ++ 3.5 C++ 14)透明運算符(如std::less<>
)存在問題,因爲當我實現自己的less<>
並自動扣除時,它運行良好。
我們不需要用'C++ 0x'來檢查類中是否存在operator <'函數。我們可以簡單地爲泛型重載模擬該函數,並將其大小用於負邏輯。請參閱下面的答案。 – iammilind 2011-04-30 05:12:56
對於那些尋求便攜式預包裝解決方案的人,有'template struct has_less:public true_type-or-false_type {};''in'#include '。文檔:http://www.boost.org/doc/libs/1_56_0/libs/type_traits/doc/html/boost_typetraits/reference/has_less。html –
alfC
2014-10-27 23:11:05