https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108487
--- Comment #8 from Mark Bourgeault <Mark_B53 at yahoo dot com> --- What about something like this? #if __cplusplus >= 201709L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) { struct PseudoRange { _InputIterator begin(); _InputIterator end(); }; if constexpr (std::ranges::random_access_range<PseudoRange>) { _M_range_initialize(__first, __last, std::random_access_iterator_tag()); } else if constexpr (std::ranges::forward_range<PseudoRange>) { _M_range_initialize(__first, __last, std::forward_iterator_tag()); } else { _M_range_initialize(__first, __last, std::__iterator_category(__first)); } #else ... #endif ----- Here is a PoC: #include <vector> #include <ranges> #include <iostream> template<typename I> void test(I first, I last) { struct PseudoRange { I begin(); I end(); }; if constexpr (std::ranges::random_access_range<PseudoRange>) { std::cout << "RA\n"; } else if constexpr (std::ranges::forward_range<PseudoRange>) { std::cout << "F\n"; } else { std::cout << "I\n"; } } int main() { auto rng = std::ranges::iota_view{0, 10} | std::views::transform([](int i) { return i*i; }); test(rng.begin(), rng.end()); auto rng2 = std::ranges::iota_view{0, 10} | std::views::filter([](int i) { return i%2; }); test(rng2.begin(), rng2.end()); return 0; }