Skip to content

Instantly share code, notes, and snippets.

@alifahrri
Last active November 9, 2019 08:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alifahrri/c538567a2774d1fd23bc6464089e3200 to your computer and use it in GitHub Desktop.
Save alifahrri/c538567a2774d1fd23bc6464089e3200 to your computer and use it in GitHub Desktop.
namespace traits {

    template <typename T, typename = void>
    struct is_std_array : std::false_type {};
    template <typename T>
    struct is_std_array<T,std::enable_if_t<
        std::is_same_v<std::array<typename T::value_type, std::tuple_size<T>::value>, T>
    > > : std::true_type {};

    template <typename T, typename = void>
    struct is_std_vector : std::false_type {};
    template <typename T>
    struct is_std_vector<T,std::enable_if_t<
        std::is_same_v<std::vector<typename T::value_type>, T>
    > > : std::true_type {};


    template <typename T, typename ...Args>
    struct is_callable {
    private:
        template <typename F>
        static constexpr auto test(int) 
            -> decltype(std::declval<F>()(std::declval<Args>()...), bool())
        { return true; }
        template <typename F>
        static constexpr auto test(char) 
        { return false; }
    public:
        constexpr static bool value = test<T>(int());
    };

    /* TODO : move (?) */
    using std::begin;
    using std::end;

    template <typename T>
    struct is_iterable {
    private:
        template <typename It>
        static constexpr auto test(int)
            -> decltype(begin(std::declval<It>()), end(std::declval<It>()), bool())
        { return true; }
        template <typename It>
        static constexpr auto test(char)
        { return false; }
    public:
        constexpr static bool value = test<T>(int());
    };

    template <typename T, typename = void>
    struct is_indexable : std::false_type {};
    template <typename T>
    struct is_indexable<T, std::void_t<decltype(std::declval<T>()[size_t{}])> > : std::true_type {};

    template <typename T, typename = void>
    struct has_push_back : std::false_type {};
    template <typename T>
    struct has_push_back<T, 
        std::void_t<decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))> 
    : std::true_type {};

    template <typename T, typename = void>
    struct has_resize : std::false_type {};
    template <typename T>
    struct has_resize<T, 
        std::void_t<decltype(std::declval<T>().resize(std::declval<typename T::size_type>()))> 
    : std::true_type {};

    template <typename T>
    using is_std_array_or_vector = std::disjunction<is_std_array<std::decay_t<T>>,is_std_vector<std::decay_t<T>>>;

} // namespace traits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment