在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