c++98 仅当 InputIt 是 T 类型的迭代器时才使用迭代器构造函数

c++98 use iterator constructor only if InputIt is an iterator of type T

对于一个学校项目,我必须实现 std::vector 但只能使用 C++98 标准。 问题是当我用带符号的整数调用它时,大小构造函数和迭代器构造函数相互冲突,所以我想到了这个(我自己实现了 enable_ifis_sameiterator_traits):

// Size constructor
explicit vector(
    size_type       count,
    const T         &value = T(),
    const Allocator &alloc = Allocator()
) : _allocator(alloc),
    _capacity(count),
    _size(count),
    _array(_allocator.allocate(_capacity)) {
    std::fill(begin(), end(), value);
}
// Iterator constructor

template <
    class InputIt
> vector(
    InputIt first, InputIt last,
    const Allocator &alloc = Allocator(),
    typename ft::enable_if< ft::is_same< typename ft::iterator_traits< InputIt >::value_type, T >::value, int >::type = 0
) : _allocator(alloc),
    _capacity(std::distance(first, last)),
    _size(_capacity),
    _array(_allocator.allocate(_capacity)) {
    std::copy(first, last, begin());
}

但是现在我的 iterator_traits 实现有问题:当我用 int 调用它时当然它不起作用,因为 int 没有迭代器成员类型,但是当我查看 cppreference 关于 iterator_traits 时,它说 If Iter does not have all five member types difference_type, value_type, pointer, reference, and iterator_category, then this template has no members by any of those names (std::iterator_traits is SFINAE-friendly) (since C++17) (until C++20) 这意味着在 C++17 之前没有实现检查,那么真正的 std::vector 甚至在 C++11 之前检查迭代器的有效性?

这是我在使用 2 ints 调用构造函数时遇到的编译器错误:

/home/crochu/Documents/42/ft_containers/iterator_traits.hpp:22:20: error: type 'int' cannot be used prior to '::' because it has no members
                typedef typename Iter::difference_type  difference_type;
                                 ^
/home/crochu/Documents/42/ft_containers/vector.hpp:78:55: note: in instantiation of template class 'ft::iterator_traits<int>' requested here
                                typename ft::enable_if< ft::is_same< typename ft::iterator_traits< InputIt >::value_type, T >::value, int >::type = 0
                                                                                  ^
/home/crochu/Documents/42/ft_containers/main.cpp:19:20: note: while substituting deduced template arguments into function template 'vector' [with InputIt = int]
        ft::vector< int >       v(5, 42);
                                ^
In file included from /home/crochu/Documents/42/ft_containers/main.cpp:13:
In file included from /home/crochu/Documents/42/ft_containers/ft_containers.hpp:15:
/home/crochu/Documents/42/ft_containers/iterator_traits.hpp:23:20: error: type 'int' cannot be used prior to '::' because it has no members
                typedef typename Iter::value_type               value_type;
                                 ^
/home/crochu/Documents/42/ft_containers/iterator_traits.hpp:24:20: error: type 'int' cannot be used prior to '::' because it has no members
                typedef typename Iter::pointer                  pointer;
                                 ^
/home/crochu/Documents/42/ft_containers/iterator_traits.hpp:25:20: error: type 'int' cannot be used prior to '::' because it has no members
                typedef typename Iter::reference                        reference;
                                 ^
/home/crochu/Documents/42/ft_containers/iterator_traits.hpp:26:20: error: type 'int' cannot be used prior to '::' because it has no members
                typedef typename Iter::iterator_category        iterator_category;
                                 ^
5 errors generated.

例如,libstdc++ 中此构造函数的实现位于 header bits/stl_vector.h:

  template<typename _InputIterator>
    vector(_InputIterator __first, _InputIterator __last,
           const allocator_type& __a = allocator_type())
    : _Base(__a)
    {
      // Check whether it's an integral type.  If so, it's not an iterator.
      typedef typename std::__is_integer<_InputIterator>::__type _Integral;
      _M_initialize_dispatch(__first, __last, _Integral());
    }

这是使用 proto-std::integral_constant class 到以下功能之一的标签分派:

  // _GLIBCXX_RESOLVE_LIB_DEFECTS
  // 438. Ambiguity in the "do the right thing" clause
  template<typename _Integer>
    void
    _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type)
    {
      this->_M_impl._M_start = _M_allocate(_S_check_init_len(
        static_cast<size_type>(__n), _M_get_Tp_allocator()));
      this->_M_impl._M_end_of_storage =
        this->_M_impl._M_start + static_cast<size_type>(__n);
      _M_fill_initialize(static_cast<size_type>(__n), __value);
    }

  // Called by the range constructor to implement [23.1.1]/9
  template<typename _InputIterator>
    void
    _M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
                           __false_type)
    {
      _M_range_initialize(__first, __last,
                          std::__iterator_category(__first));
    }

我想说这已经是您在限制条件下所能达到的最优雅的程度了!