BCC582 (C++Builder 2006) では問題なかった下記のような自前のインサートイテレータがあります。
template <class X> class MyInsertIterator { public: MyInsertIterator(X& x) : x_(&x) {}; MyInsertIterator& operator = (const Foo& v) { x_->Add(v); return *this; } MyInsertIterator& operator * () { return *this; } MyInsertIterator& operator ++ () { return *this; } MyInsertIterator& operator ++ (int) { return *this; } protected: X* x_; }; template <class X> inline MyInsertIterator<X> MyInserter(X& x) { return MyInsertIterator<X>(x); }
これを std::copy で使っているのですが、VC141 (Visual Studio 2017 の Visual C++) でデバッグ用ビルドすると warning C4996 と error C2794 が報告されます。
まず error C2794 対策、
エラーメッセージは
'iterator_category': 'std::iterator_traits<_Iter>' の基底クラスの直接的または間接的なメンバーではありません。
ですが、イテレータの特性が取得できないみたいです。そこで MyInsertIterator クラス定義内に以下を追加します。
public: using iterator_category = std::output_iterator_tag; using difference_type = void; using value_type = void; using pointer = void; using reference = void; using container_type = X;
つづいて warning C4996 対策、
警告メッセージは
'std::copy::_Unchecked_iterators::_Deprecate': Call to 'std::copy' with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
ということで、マクロ _SCL_SECURE_NO_WARNINGS を定義するとか、pragma で warning C4996 を無効にしてしまう方法もありますが、他への影響を最小限にするため、MyInsertIterator クラス定義の後に以下を追加してイテレータを checked の扱いにしてしまいます。
template<class _Container> struct std::_Is_checked_helper<MyInsertIterator<_Container> > : public std::true_type {};
最後に、全体のコード例を載せて起きます。
長くなりそうだったので X::Add(Foo) の代わりに X::push_back(int) になってます。
#include <iostream> #include <algorithm> #include <iterator> #include <vector> using namespace std; template <class X> class MyInsertIterator { public: using iterator_category = output_iterator_tag; using difference_type = void; using value_type = void; using pointer = void; using reference = void; using container_type = X; MyInsertIterator(X& x) : x_(&x) {}; MyInsertIterator& operator = (const typename X::value_type& v) { x_->push_back(v); return *this; } MyInsertIterator& operator * () { return *this; } MyInsertIterator& operator ++ () { return *this; } MyInsertIterator& operator ++ (int) { return *this; } protected: X* x_; }; template <class X> struct _Is_checked_helper<MyInsertIterator<X> > : public true_type {}; template <class X> inline MyInsertIterator<X> MyInserter(X& x) { return MyInsertIterator<X>(x); } int main() { vector<int> v = { 2, 3, 5, 7, 11, 13 }; vector<int> w; copy(v.begin(), v.end(), MyInserter(w)); cout << "w:"; for (auto& i : v) { cout << ' ' << i; } cout << endl; }