How to distinguish fill constructor and range constructor in C ++ 11?

I suspect that the prototypes of the fill constructor and the range constructor std::vector(and many other types of STLs) given in this web page are not correct, so I am implementing NaiveVectorto simulate these two prototypes.

My code is:

#include <iostream>
#include <vector>
using namespace std;

template <typename T>
struct NaiveVector {
  vector<T> v;
  NaiveVector(size_t num, const T &val) : v(num, val) { // fill
    cout << "(int num, const T &val)" << endl;
  }

  template <typename InputIterator>
  NaiveVector(InputIterator first, InputIterator last) : v(first, last) { // range
    cout << "(InputIterator first, InputIterator last)" << endl;
  }

  size_t size() const { return v.size(); }
};

int main() {
  NaiveVector<int> myVec1(5,1);                   // A
  cout << "size = " << myVec1.size() << endl;
  for (auto n : myVec1.v) { cout << n << " "; }
  cout << endl;

  cout << "-----" << endl;

  vector<int> vec({1,2,3,4,5});               
  NaiveVector<int> myVec2(vec.begin(), vec.end());// B
  cout << "size = " << myVec2.size() << endl;
  for (auto n : myVec2.v) { cout << n << " "; }
  cout << endl;
}

And the result:

$ g++ overload.cc -o overload -std=c++11
$ ./overload
(InputIterator first, InputIterator last) // should be: (int num, const T &val)
size = 5
1 1 1 1 1
-----
(InputIterator first, InputIterator last)
size = 5
1 2 3 4 5

As I suspected from the start, the compiler cannot distinguish the two constructors properly. Then my question is : how do the fill std::vectorconstructor and range constructor differ from each other?

To rephrase : how to implement two constructors of this NaiveVector?

, . , ++ 11 is_iterator<>.. ( MSVC ).

: rval ​​ lvalue, NaiveVector A.

+1
3

++ 03

[lib.sequence.reqmts]/9

, 21:

  • template <class InputIterator>
    X(InputIterator f, InputIterator l, const Allocator& a = Allocator())
    

    , :

    X(static_cast<typename X::size_type>(f),
      static_cast<typename X::value_type>(l),
      a)
    

    InputIterator .

...

[lib.sequence.reqmts]/11

, , , - . .

, , , "" , , .

++ 11/++, 14

[sequence.reqmts]/14

, 21:

  • template <class InputIterator>
    X(InputIterator first, InputIterator last,
      const allocator_type& alloc = allocator_type())
    

    InputIterator, , ....

[sequence.reqmts]/15

, , , , , .

SFINAE ( ++ 11, ++ 03).

++ 17

, , , , [container.requirements.general]/17.

, :

template <typename InputIterator,
          typename = std::enable_if<is_likely_iterator<InputIterator>>::type>
NaiveVector(InputIterator first, InputIterator last)

is_iterator , - , , , std::iterator_traits, , ( ). . libstd++, lib++

std::vector ++ 11 . ( , std::vector ), , , , , " " , . ( , ). ++ 03 std::vector " ", .

+5

http://en.cppreference.com/w/cpp/container/vector/vector, ( ):

4) [first, last).

, vector(static_cast<size_type>(first), static_cast<value_type>(last), a), InputIt . ( ++ 11)

, InputIt InputIterator, (2).

std::vector, , . , , , std::vector.

,

NaiveVector<int> myVec1(5,1);

, int - . int size_t, . , .

+2

, , T:

template
<
    typename InputIterator
,   typename = typename ::std::enable_if
    <
        ::std::is_same
        <
            T &
        ,   typename ::std::remove_const
            <
                decltype(*(::std::declval< InputIterator >()))
            >::type
        >::value
    ,  void
    >::type
>
NaiveVector(InputIterator first, InputIterator last) : v(first, last)
{
    cout << "(InputIterator first, InputIterator last)" << endl;
}

+1

Source: https://habr.com/ru/post/1684502/


All Articles