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
任意の演算子のより一般的な解決策 (UPDATE 2014)
std::less
(binary) やstd::negate
(unary)などの STD 演算子ラッパーを介して、すべての組み込み演算子にもアクセスできる (場合によっては特殊化されている) という事実を利用する、より一般的なソリューションがあります。
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 標準ライブラリでは、C++14 の標準である、C++11 で手動で透明な演算子を実装できますdecltype(std::less<random_type>()(...))
。random_type
)
構文は非常にスムーズです。このようなものが標準に採用されることを望みます。
2 つの拡張子:
1) raw 関数アプリケーションを検出するために機能します。
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'
注: http://melpon.org/wandbox/で C++14 を使用してコードをコンパイルしようとしましたが、うまくいきませんでした。std::less<>
その実装(clang ++ 3.5 c ++ 14)では、透過的な演算子( など)に問題があると思いますless<>
。自動推定で独自に実装するとうまく機能するからです。