/** * @file has_operator.hpp * @brief J Library TraitsUtil ヘッダファイル。 * @copyright 2024 Nomura Kei * @depends * * テンプレートメソッドの引数に渡されたクラスが、operator を持っているか判定します。 * @code * 使用例 * template <typename T> * class ArrayList { * public: * ArrayList() = default; * virtual ~ArrayList() = default; * std::string toString() const * { * std::ostringstream oss; * for (const auto& e : items) * { * if constexpr (hasOperatorOutput<T>::value) * { // 要素の型(クラス)が、operator<< を持っている * oss << e; * } * else * { * oss < "<unknown>"; * } * } * } * private: * std::vector<T> items; * }; * @endcode * */ #ifndef J_HAS_OPERATOR_HPP #define J_HAS_OPERATOR_HPP #include <ostream> #include <istream> #include <type_traits> // operator<< 存在チェック template <typename T, typename = void> struct hasOperatorOutput : std::false_type { }; template <typename T> struct hasOperatorOutput<T, std::void_t<decltype(std::declval<std::ostream &>() << std::declval<T>())>> : std::true_type { }; // operator>> 存在チェック template <typename T, typename = void> struct hasOperatorInput : std::false_type { }; template <typename T> struct hasOperatorInput<T, std::void_t<decltype(std::declval<std::istream &>() >> std::declval<T &>())>> : std::true_type { }; // operator== 存在チェック template <typename T, typename = void> struct hasOperatorEq : std::false_type { }; template <typename T> struct hasOperatorEq<T, std::void_t<decltype(std::declval<T>() == std::declval<T>())>> : std::true_type { }; // operator!= 存在チェック template <typename T, typename = void> struct hasOperatorNotEq : std::false_type { }; template <typename T> struct hasOperatorNotEq<T, std::void_t<decltype(std::declval<T>() != std::declval<T>())>> : std::true_type { }; // operator< 存在チェック template <typename T, typename = void> struct hasOperatorLt : std::false_type { }; template <typename T> struct hasOperatorLt<T, std::void_t<decltype(std::declval<T>() < std::declval<T>())>> : std::true_type { }; // operator> 存在チェック template <typename T, typename = void> struct hasOperatorGt : std::false_type { }; template <typename T> struct hasOperatorGt<T, std::void_t<decltype(std::declval<T>() > std::declval<T>())>> : std::true_type { }; // operator<= 存在チェック template <typename T, typename = void> struct hasOperatorLtEq : std::false_type { }; template <typename T> struct hasOperatorLtEq<T, std::void_t<decltype(std::declval<T>() <= std::declval<T>())>> : std::true_type { }; // operator>= 存在チェック template <typename T, typename = void> struct hasOperatorGtEq : std::false_type { }; template <typename T> struct hasOperatorGtEq<T, std::void_t<decltype(std::declval<T>() >= std::declval<T>())>> : std::true_type { }; // operator+ 存在チェック template <typename T, typename = void> struct hasOperatorAdd : std::false_type { }; template <typename T> struct hasOperatorAdd<T, std::void_t<decltype(std::declval<T>() + std::declval<T>())>> : std::true_type { }; // operator+= 存在チェック template <typename T, typename = void> struct hasOperatorAddEq : std::false_type { }; template <typename T> struct hasOperatorAddEq<T, std::void_t<decltype(std::declval<T &>() += std::declval<T>())>> : std::true_type { }; // operator- 存在チェック template <typename T, typename = void> struct hasOperatorSub : std::false_type { }; template <typename T> struct hasOperatorSub<T, std::void_t<decltype(std::declval<T>() - std::declval<T>())>> : std::true_type { }; // operator-= 存在チェック template <typename T, typename = void> struct hasOperatorSubEq : std::false_type { }; template <typename T> struct hasOperatorSubEq<T, std::void_t<decltype(std::declval<T &>() -= std::declval<T>())>> : std::true_type { }; // operator* 存在チェック template <typename T, typename = void> struct hasOperatorMul : std::false_type { }; template <typename T> struct hasOperatorMul<T, std::void_t<decltype(std::declval<T>() * std::declval<T>())>> : std::true_type { }; // operator*= 存在チェック template <typename T, typename = void> struct hasOperatorMulEq : std::false_type { }; template <typename T> struct hasOperatorMulEq<T, std::void_t<decltype(std::declval<T &>() *= std::declval<T>())>> : std::true_type { }; // operator/ 存在チェック template <typename T, typename = void> struct hasOperatorDiv : std::false_type { }; template <typename T> struct hasOperatorDiv<T, std::void_t<decltype(std::declval<T>() / std::declval<T>())>> : std::true_type { }; // operator/= 存在チェック template <typename T, typename = void> struct hasOperatorDivEq : std::false_type { }; template <typename T> struct hasOperatorDivEq<T, std::void_t<decltype(std::declval<T &>() /= std::declval<T>())>> : std::true_type { }; #endif // J_HAS_OPERATOR_HPP