Prev: Job for Boost filtered iterators ???
Next: State of N2801: initializer lists and move semantics
From: Rem on 3 Jul 2010 17:42 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? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Bo Persson on 4 Jul 2010 02:43 Rem wrote: > 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? Right now, you have to call end() on a const vector to get a const_iterator. You could possibly make 'integers' const, or form a const reference to it: const std:vector<int>& const_integer = integer; A a2(i, const_integer.end(); In C++0x (and Visual C++ 2010) the standard containers also have cbegin() and cend() members, that always return const_iterators. Help is on its way! Bo Persson -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Paul Bibbings on 4 Jul 2010 05:48 Rem <therealremi(a)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! ]
From: Stuart Golodetz on 4 Jul 2010 05:52 On 04/07/2010 09:42, Rem wrote: > 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? The non-const end() method gets called because integers isn't const. To call the const version, you can do e.g. A a2(i, const_cast<const std::vector<int>&>(integers).end()); Or clearer: const std::vector<int>& cintegers = integers; A a2(i, cintegers.end()); I think I'm right in saying that cbegin() and cend() methods have been added to things like std::vector in C++0x to get around this sort of issue. Regards, Stu -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Pete Becker on 4 Jul 2010 06:57 On 2010-07-03 22:42:26 -0400, Rem said: > 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. Don't guess. Learn the rules. The template constructor takes two arguments of the same type. The code passes two different types: the first argument has type const_iterator and the second is iterator. The choice of an overloaded function depends on the arguments, not on how the result is used. The compiler picks the non-const version of end() because the integers object is not const. The old way of getting around this was static_cast<const std::vector<T>&>(integers).end(). The new way is integers.cend(). -- Pete Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The Standard C++ Library Extensions: a Tutorial and Reference (www.petebecker.com/tr1book) [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 Prev: Job for Boost filtered iterators ??? Next: State of N2801: initializer lists and move semantics |