Combine tipos iteráveis (matrizes e classes com begin () / end ())

Eu escrevi traços de tipo como classes que podem ser usadas para testar se um determinado tipo é "iterável". Isso vale para matrizes (paraT[N], não paraT[]) e para classes que têm umbegin e umend método que retorna coisas que se parecem com iteradores. Gostaria de saber se isso pode ser feito de forma mais concisa / simples do que eu fiz.

Especialmente as coisas noimpl namespace parece um pouco rotativo / hacky. Tudo parece um pouco feio para mim. Para um exemplo que usa isso e pode ser compilado com g ++ e clang ++, consulte:https://gist.github.com/panzi/869728c9879dcd4fffa8

template<typename T>
struct is_iterator {
private:
    template<typename I> static constexpr auto test(void*)
        -> decltype(
            *std::declval<const I>(),
            std::declval<const I>() == std::declval<const I>(),
            std::declval<const I>() != std::declval<const I>(),
            ++ (*std::declval<I*>()),
            (*std::declval<I*>()) ++,
            std::true_type()) { return std::true_type(); }

    template<typename I> static constexpr std::false_type test(...) { return std::false_type(); }

public:
    static constexpr const bool value = std::is_same<decltype(test<T>(0)), std::true_type>::value;
};

namespace impl {
    // implementation details

    template<typename T>
    struct has_iterable_methods {
    private:

        template<typename C> static constexpr auto test(void*)
            -> decltype(
                std::declval<C>().begin(),
                std::declval<C>().end(),
                std::true_type()) { return std::true_type(); }

        template<typename C> static constexpr std::false_type test(...) { return std::false_type(); }

    public:
        static constexpr const bool value = std::is_same<decltype(test<T>(0)), std::true_type>::value;
    };

    template<typename T, bool HasIterableMethods>
    struct returns_iterators : public std::false_type {};

    template<typename T>
    struct returns_iterators<T, true> {
        typedef decltype(std::declval<T>().begin()) begin_type;
        typedef decltype(std::declval<T>().end())   end_type;

        static constexpr const bool value =
            std::is_same<begin_type, end_type>::value &&
            is_iterator<begin_type>::value;
    };
}

template<typename T>
struct is_iterable : public std::integral_constant<
    bool,
    impl::returns_iterators<
        typename std::remove_const<T>::type,
        impl::has_iterable_methods<typename std::remove_const<T>::type>::value>::value> {};

template<typename T, std::size_t N>
struct is_iterable<T[N]> : public std::true_type {};

template<typename T>
struct is_iterable<T*> : public std::false_type {};

questionAnswers(1)

yourAnswerToTheQuestion