Hello,

Can anybody explain why I got an awful error message when try following code:

#include <vector>

int main()
{
     std::vector<const int> v;
    return 0;
}

Thanks in advance,
brain.

What is the error-message? What compiler are you using?
This compiles fine on VS2008 with warninglevel 4.
And why do you want to use const ints?

What is the error-message? What compiler are you using?
This compiles fine on VS2008 with warninglevel 4.
And why do you want to use const ints?

I use gcc version 4.2.2 20070909 (prerelease) (4.2.2-0.RC.1mdv2008.0).

I just want to keep the vector from constant integers.

The error message is the following:
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/ext/new_allocator.h: In instantiation of ‘__gnu_cxx::new_allocator<const int>’:
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/bits/allocator.h:86: instantiated from ‘std::allocator<const int>’
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/bits/stl_vector.h:79: instantiated from ‘std::_Vector_base<const int, std::allocator<const int> >’
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/bits/stl_vector.h:160: instantiated from ‘std::vector<const int, std::allocator<const int> >’
test.cpp:18: instantiated from here
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/ext/new_allocator.h:81: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const [with _Tp = const int]’ cannot be overloaded
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/ext/new_allocator.h:78: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const int]’
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::deallocate(_Tp*, size_t) [with _Tp = const int]’:
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/bits/stl_vector.h:134: instantiated from ‘void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(_Tp*, size_t) [with _Tp = const int, _Alloc = std::allocator<const int>]’
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/bits/stl_vector.h:120: instantiated from ‘std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = const int, _Alloc = std::allocator<const int>]’
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/bits/stl_vector.h:199: instantiated from ‘std::vector<_Tp, _Alloc>::vector(const _Alloc&) [with _Tp = const int, _Alloc = std::allocator<const int>]’
test.cpp:18: instantiated from here
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/ext/new_allocator.h:97: error: invalid conversion from ‘const void*’ to ‘void*’
/usr/lib/gcc/i586-mandriva-linux-gnu/4.2.2/../../../../include/c++/4.2.2/ext/new_allocator.h:97: error: initializing argument 1 of ‘void operator delete(void*)’

Try this,

#include <vector>
     #include<iostream>
     using namespace std;
      int main()
      {
        vector<const int*> v;
        return 0;
      }

try

#include <vector>

int main() {
	std::vector<const int> v();
	return 0;
}

Thanks. it helps.

But I cannot add any element to it.
v.push_back(5);

causes error message.

Ok, thank you, but I was confused because Visual C++ 2005 compiler lets the following code:

#include <vector>


int main()
{
std::vector<const int> v;
v.push_back(5);
v[0] = 2;
return 0;
}

I also would like to understand if following code cannot be compiled:

#include <vector>
#include <iostream>


void f(std::vector<int>::const_iterator& i)
{
std::cout << *i << std::endl;
}
int main()
{
std::vector<int> v;
for (std::vector<int>::iterator b = v.begin(); b != v.end(); ++b)
f(b);
return 0;
}

but if the prototype of the function is the following everything is OK.

void f(const std::vector<int>::const_iterator& i); or
void f(std::vector<int>::const_iterator i);

Regards,
brain.

Edited 3 Years Ago by happygeek: fixed formatting

for a standard container, begin() and end() are overloaded on the const specifier.
on a modifiable container, begin() and end() return container::iterator.
on a const container, begin() and end() returns container::const_iterator.

template< typename CNTR > // CNTR is a standard container
void foo( CNTR& cntr, const CNTR& const_cntr )
{
  typename CNTR::iterator iter = cntr.begin() ;
  typename CNTR::const_iterator const_iter = const_cntr.begin() ;
  typename CNTR::reverse_iterator rev_iter = cntr.rbegin() ;
  typename CNTR::const_reverse_iterator const_rev_iter = const_cntr.rbegin() ;
}

this code will not compile:

#include <vector>

void f( std::vector<int>::const_iterator& i )
{ std::cout << *i << std::endl; }

int main()
{
  std::vector<int> v;
  std::vector<int>::iterator b = v.begin() ;
  f(b);
}

but this will:

template< typename ITERATOR > void f( ITERATOR i )
{  std::cout << *i << std::endl; }

#include <vector>

int main()
{
  std::vector<int> v;
  std::vector<int>::iterator b = v.begin() ;
  f(b);
}

c++09: containers also have:

// ...
  const_iterator cbegin() const;
  const_iterator cend () const;
  const_reverse_iterator crbegin() const;
  const_reverse_iterator crend () const;
// ...

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1674.pdf
so things become a bit more convenient.

note: prefer passing an iterator by value (rather than by modifiable reference);
it is more flexible for iterations to be non-intrusive.

Comments
good info!

for a standard container, begin() and end() are overloaded on the const specifier.
on a modifiable container, begin() and end() return container::iterator.
on a const container, begin() and end() returns container::const_iterator.

template< typename CNTR > // CNTR is a standard container
void foo( CNTR& cntr, const CNTR& const_cntr )
{
  typename CNTR::iterator iter = cntr.begin() ;
  typename CNTR::const_iterator const_iter = const_cntr.begin() ;
  typename CNTR::reverse_iterator rev_iter = cntr.rbegin() ;
  typename CNTR::const_reverse_iterator const_rev_iter = const_cntr.rbegin() ;
}

this code will not compile:

#include <vector>

void f( std::vector<int>::const_iterator& i )
{ std::cout << *i << std::endl; }

int main()
{
  std::vector<int> v;
  std::vector<int>::iterator b = v.begin() ;
  f(b);
}

but this will:

template< typename ITERATOR > void f( ITERATOR i )
{  std::cout << *i << std::endl; }

#include <vector>

int main()
{
  std::vector<int> v;
  std::vector<int>::iterator b = v.begin() ;
  f(b);
}

c++09: containers also have:

// ...
  const_iterator cbegin() const;
  const_iterator cend () const;
  const_reverse_iterator crbegin() const;
  const_reverse_iterator crend () const;
// ...

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1674.pdf
so things become a bit more convenient.

note: prefer passing an iterator by value (rather than by modifiable reference);
it is more flexible for iterations to be non-intrusive.

Thanks everybody for discussion.:)

This article has been dead for over six months. Start a new discussion instead.