Finding the common iterator category in C++
If you have a typelist of iterator tag types, then std::common_type will find the common base type.  

using InTag = std::istream_iterator&lt;int&gt;::iterator_category;
using BdTag = std::list&lt;int&gt;::iterator::iterator_category;
using RaTag = std::vector&lt;int&gt;::iterator::iterator_category;

static_assert(std::is_same_v&lt;std::common_type_t&lt;InTag, BdTag&gt;, std::input_iterator_tag&gt;);
static_assert(std::is_same_v&lt;std::common_type_t&lt;InTag, RaTag&gt;, std::input_iterator_tag&gt;);
static_assert(std::is_same_v&lt;std::common_type_t&lt;BdTag, RaTag&gt;, std::bidirectional_iterator_tag&gt;);


If you are unwrapping the tag type at the call site, just have the trait do it.

template &lt;class... Iterators&gt;
struct common_iterator_tag 
: std::common_type&lt;typename std::iterator_traits&lt;Iterators&gt;::iterator_category...&gt;
{
};

template &lt;class... Iterators&gt;
using common_iterator_tag_t = typename common_iterator_tag&lt;Iterators...&gt;::type;

using RaIter = std::vector&lt;int&gt;::iterator;
using InIter = std::istream_iterator&lt;int&gt;::iterator;

static_assert(std::is_same_v&lt;std::input_iterator_tag, common_iterator_tag_t&lt;RaIter, InIter&gt;&gt;);

using BackIter = std::back_insert_iterator&lt;std::vector&lt;int&gt;&gt;;
using InsertIter = std::insert_iterator&lt;std::list&lt;int&gt;&gt;;

static_assert(std::is_same_v&lt;std::output_iterator_tag, common_iterator_tag_t&lt;BackIter, InsertIter&gt;&gt;);