Accelerated C++の第11章では、STLのベクトルクラスの簡略版を例として、テンプレートクラスの実装について説明しています。エクササイズ11-6では、.erase()
と.clear()
のメソッドをクラスに追加したいので、最初に最終コードをブックから直接コピーしてコンパイルしようとしましたが、失敗しました。その後、すべての関数定義を.hファイルに移動し(必要に応じてVec<T>::
などを削除して)、main.cppをコンパイルしました。ここで簡略化されたC++ベクタークラスのコピーの実装 -
は、私のコードのすべてです:
main.cppに
#include <iostream>
#include "Vec.h"
using std::cout;
using std::endl;
int main()
{
Vec<int> v;
for (int i = 1; i < 10; ++i)
v.push_back(i);
for(Vec<int>::const_iterator iter = v.begin();
iter != v.end(); ++iter)
cout << *iter << endl;
return 0;
}
Vec.h
#ifndef GUARD_Vec_h
#define GUARD_Vec_h
#include <cstddef>
#include <memory>
template <class T> class Vec {
public:
// member variables
typedef T* iterator;
typedef const T* const_iterator;
typedef std::size_t size_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
// constructors + destructors
Vec() { create(); }
explicit Vec(size_type n, const T& t = T()) { create(n, t); }
Vec(const Vec& v) { create(v.begin(), v.end()); }
~Vec() { uncreate(); }
// methods
T& operator[](size_type i) { return data[i]; }
const T& operator[](size_type i) const { return data[i]; }
void push_back(const T& t) {
if (avail == limit)
grow();
unchecked_append(t);
}
size_type size() const { return avail - data; }
iterator begin() { return data; }
const_iterator begin() const { return data; }
iterator end() { return avail; }
const_iterator end() const { return avail; }
private:
iterator data;
iterator avail;
iterator limit;
std::allocator<T> alloc;
void create();
void create(size_type, const T&);
void create(const_iterator, const_iterator);
void uncreate();
void grow();
void unchecked_append(const T&);
};
#endif GUARD_Vec_h
Vec.cpp
#include <algorithm>
#include <cstddef>
#include <memory>
#include "Vec.h"
using std::allocator;
using std::max;
using std::uninitialized_copy;
using std::uninitialized_fill;
using std::ptrdiff_t;
template <class T> void Vec<T>::create()
{
data = avail = limit = 0;
}
template <class T> void Vec<T>::create(size_type n, const T& val)
{
data = alloc.allocate(n);
limit = avail = data + n;
uninitialized_fill(data, limit, val);
}
template <class T> void Vec<T>::create(const_iterator i, const_iterator j)
{
data = alloc.allocate(j - i);
limit = avail = uninitialized_copy(i, j, data);
}
template <class T> void Vec<T>::uncreate()
{
if (data) {
iterator it = avail;
while (it != data)
alloc.destroy(--it);
alloc.deallocate(data, limit - data);
}
data = limit = avail = 0;
}
template <class T> void Vec<T>::grow()
{
size_type new_size = max(2 * (limit - data), ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
iterator new_avail = uninitialized_copy(data, avail, new_data);
uncreate();
data = new_data;
avail = new_avail;
limit = data + new_size;
}
template <class T> void Vec<T>::unchecked_append(const T& val)
{
alloc.construct(avail++, val);
}
はなぜこのコンパイルを行います?
テンプレート定義をヘッダファイルに入れなければならない理由を説明していないと考えるのは非常に難しいです。いずれにせよ、[this](http://www.parashift.com/c++-faq -lite/templates.html#faq-35.15)。 – ildjarn
著者は.hと.cppファイルに分割された 'Vec'を入れたようです。そうだとすれば、彼はかわいらしいコンパイラを持っていなければなりません! –
Hm、たぶん私は間違っている/間違っているかもしれないが、私はそれがそこにあると思うが、そのことを言及している本を思い出すことはない(加速的なC++は全体的に本当に良い本だと思われる)...助けてくれてありがとう! * EDIT * 2番目の考えで..本はテンプレートが最初に導入されたときにこれをいくつかの章に言及しました。忘れてしまった私のせいです。 – adelbertc