Newer
Older
libj / include / j / has_operator.hpp
/**
 * @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