eigener 'Checked Iterator' in Visual C++
-
Unter 'Visual C++' (ca. ab 8.0) gibt es das Konzept von 'Checked Iterators', was ganz hilfreich ist, aber den unangenehmen Seiteneffekt hat, dass selbst geschriebene Iteratoren dort nicht ohne weiteres drunter fallen.
Ganz konkret hab ich einen selbst geschriebenen Output-Iterator, den ich an den copy-Algorithmus übergebe. Und bekomme beim Compilieren die Warnung: "warning C4996: 'std::copy': Function call with parameters that may be unsafe - ..".
Frage: wie muss ich meinem Iterator erweitern, damit diese Warnung nicht mehr kommt?
Bis jetzt hab ich nur herausgefunden, dass es dort ein #define _IF_CHK gibt und man es über Spezialisierungen von std::_Is_checked_iterator und std::_Checked_iterator_category hinkriegen sollte (alles in <xutility>). Aber bis jetzt ist es mir nicht gelungen. Und diese komische Firma aus Redmond scheint auch nicht davon auszugehen, dass jemand seine eigenen Iteratoren schreibt ... also muss man das auch nicht dokumentieren - oder!?
Ach ja: mein Iterator ist auch ein Template (wie sollte es auch anders sein).
Gruß
Werner
-
Leite von stdext::checked_iterator ab, anstatt von std::iterator.
Simon
-
Hallo Simon,
.. die warning bleibt leider. Das macht keinen Unterschied.
-
das hier mal versucht!?
<a href= schrieb:
MSDN">
// C4996_b.cpp // compile with: /EHsc /W1 #define _SECURE_SCL 1 #include <algorithm> using namespace std; using namespace stdext; int main() { int a [] = {1, 2, 3}; int b [] = {10, 11, 12}; copy(a, a + 3, b); // C4996 copy(a, a + 3, checked_array_iterator<int *>(b, 3)); // OK }ich würd btw einfach die 4996er warning deaktivieren... wäre einfacher und idR weiß ich selbst, welche Fkt ich aufrufen sollte und welche nicht

wenn du das nicht willst, kannst du ja mal gucken, ob
checked_array_iteratorim namespace stdext ist und ob du deinen iterator davon ableiten darfst ^^bb
-
geht.
// iter.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. // #include "stdafx.h" #define _SECURE_SCL 1 #include <vector> #include <xutility> #include <iostream> using namespace std; struct PrintIntIterator:public iterator<output_iterator_tag,int>{ typedef _Range_checked_iterator_tag _Checked_iterator_category;//<--- int value; PrintIntIterator& operator++(){ cout<<value<<'\n'; return *this; } int& operator*(){ return value; } }; int _tmain(int argc, _TCHAR* argv[]) { vector<int> vec; for(int i=0;i!=10;++i) vec.push_back(i*i); copy(vec.begin(),vec.end(),PrintIntIterator()); return 0; }
-
Danke Volkard,
so geht's tatsächlich

Gruß
Werner
-
Wäre nett, wenn Du Deinen Iterator mal zeigen würdest, wenn Du mit ihm zufrieden bist, damit ich zurücklerne.
Ich hab ja nix gemacht, außer die SFINAE-Templates aufzudröseln, ohne zu wissen, was ich gemacht hab. Ich weiß aber nicht, wie man einen output iterator eigentlich ordentlich macht.
-
volkard schrieb:
Wäre nett, wenn Du Deinen Iterator mal zeigen würdest, wenn Du mit ihm zufrieden bist, damit ich zurücklerne.
Das ist kein Hexenwerk - ich hatte einfach frech den std::ostream_iterator aus <iterator> kopiert (allerdings schon vor Jahren, daher die Variante ohne Checked Iterator) und den Typ std::ostream durch einen eigenen binären Stream ersetzt. (s. C++-Standard [lib.ostream.iterator] Kapitel 24.5.2)
#include "obinstream.h" #include <iterator> template< class T > class obinstream_iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > { public: typedef obinstream::char_type char_type; typedef obinstream::traits_type traits_type; typedef obinstream ostream_type; #if _SECURE_SCL typedef std::_Range_checked_iterator_tag _Checked_iterator_category; #endif explicit obinstream_iterator( ostream_type& _O ) : _Ostr(&_O) {} obinstream_iterator<T>& operator=( const T& _X ) {*_Ostr << _X; return (*this); } obinstream_iterator<T>& operator*() {return (*this); } obinstream_iterator<T>& operator++() {return (*this); } obinstream_iterator<T> operator++(int) {return (*this); } protected: ostream_type *_Ostr; };volkard schrieb:
Ich hab ja nix gemacht, außer die SFINAE-Templates aufzudröseln, ohne zu wissen, was ich gemacht hab.
Das war auch meine Vorgehensweise - ich hatte bloß beim Übersetzen aus Versehen zwei Dateien im Archiv vertauscht - also eine Datei geändert, aber eine andere compiliert
. Daher fruchtete auch keine der Änderungen.Falls Du mehr eigene Iteratoren schreiben willst, so kann ich Dir boost.iterator wärmstens empfehlen. Wenn man erstmal kapiert hat, wie iterator_adaptor und iterator_facade ticken, ist es echt genial.
Gruß
Werner
-
Ich hatte das Schreiben in den op++ gelegt und wußte, daß das nicht ok ist. Daher meine Unsicherheit. Einen Proxy für den op= einsetzen wollte ich nicht gerade.
Dabei ist
obinstream_iterator<T>& operator*() {return (*this); }so einfach. lol.