Re: enforcing const overload of a method
Rem <therealremi@gmail.com> writes:
Please take a look at this code:
class A
{
public:
template<class XIter>
A(const XIter begin, const XIter beyond)
{}
};
#include <vector>
int main(int argc, char* argv[])
{
std::vector<int> integers;
A a1( integers.begin(), integers.end() );//No problem
std::vector<int>::const_iterator i( ++( integers.begin() ) );//
compiler doesn't like const_iterator here
A a2( i, integers.end() );//error C2660: 'A::A' : function does not
take 2 arguments
return 0;
}
What happened here is that in a2 constructor call Visual C++ 2008 was
unable to choose the const version of std::vector<T>::end() - or so I
guess. The error message is very confusing.
Do you know how I can make sure that the const_iterator is picked as a
template argument instead of iterator?
As you might expect when you think a little more about it, the
std::vector member functions begin() and end() exist each as a pair of
overloads (const and non-const):
namespace std {
template<class T, class Allocator = allocator<T> >
class vector {
public:
// ...
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
// ...
};
}
The non-const overloads return an iterator and the const overloads
return a const_iterator. As is the nature of when and how selection
is
made between such overloads, the difference is the constness (or
otherwise) of the std::vector instance on which the particular method
is
invoked.
A a2( i, integers.end() );// error C2660: 'A::A' : function does not
// take 2 arguments
Here, i is a const_iterator. However, since end() is called on a
non-const std::vector<int>, this call will produce an iterator. Since
the types of the two arguments to the constructor call are then
different the invocation fails to find the constructor which is singly
parameterized on XIter. Thus the error, as given, doesn't relate to
the
constructor at all but is rather a failure against the compiler-
generated
copy-constructor A(const A&).
Although I do not suggest this as the way to correct your example, the
following illustrates what is going on here:
int main()
{
std::vector<int> integers;
std::vector<int>::const_iterator i(++(integers.begin()));
const std::vector<int>& integers_cref = integers;
A a2(i, integers_cref.end()); // Works: const_iterator for
arg2
}
Also, in your example you have declared the parameters to the
constructor for A to be of type const XIter. This is almost certainly
not what you want, either for iterators or for const_iterators, since
you will not then be able to use the increment/decrement/etc.
operators
upon them.
Regards
Paul Bibbings
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]