ポインタのコレクションを使用しないでください。ヒープに割り当てられた単語の実装が必要な場合は、値のような振る舞いを持つハンドルクラスで囲みます。
そして(ETC、またはベクター)リストに格納
例えばは:
struct word_impl {}; // big thing
auto clone(const word_impl& impl) -> std::unique_ptr<word_impl> {
// clone could if you wished, defer to a virtual clone method
// on word_impl
return std::make_unique<word_impl>(impl);
}
struct word
{
// construct from letters
word(const char* letters) : impl_ { std::make_unique<word_impl>(letters) } { }
// let's make it copyable
word(const word& r) : impl_ { clone(r.impl_) } {}
word& operator=(const word& r) {
if (this != std::addressof(r)) {
impl_ = clone(r.impl_);
}
return *this;
}
// and moveable
word(word&& r) = default;
word& operator=(word&& r) = default;
private:
std::unique_ptr<word_impl> impl_;
}
ここで両方の共有及び複製可能な単語の用語の単語オブジェクトを表す完全な、コンパイル例です。
私がここでやろうとしたことは、「共感」と実際の単語の操作との分離です。
これにより、クライアントサイトで同じコードを使用して、一意の単語または共有単語の文を作成することができます。ユーザーは、単語の内部動作やメモリの管理方法についての知識は必要ありません。彼が知る必要があるのは、それをコピーし、印刷し、比較することができることだけです(この場合)。
さらに、unique_wordをshared_wordに変換する操作もあります。
#include <memory>
#include <iostream>
#include <vector>
#include <iomanip>
#include <boost/operators.hpp>
//
// define some protocols that a handle class can inherit from. These
// translate methods on the handle onto methods on the implementation
//
template<class Handle>
struct implement_ostream_protocol {
friend std::ostream &operator<<(std::ostream &os, const implement_ostream_protocol &proto) {
auto &ref = static_cast<const Handle &>(proto).get_reference();
return os << ref;
}
};
template<class Handle, class Comp = std::less<>>
struct implement_less_than_protocol {
friend bool operator<(const implement_less_than_protocol &l, const implement_less_than_protocol &r) {
auto &lr = static_cast<const Handle &>(l).get_reference();
auto &rr = static_cast<const Handle &>(r).get_reference();
auto comp = Comp();
return comp(lr, rr);
}
};
template<class Handle>
struct implement_setValue_protocol {
template<class T>
decltype(auto) setValue(T&& value)
{
auto &lr = static_cast<Handle &>(*this).get_reference();
return lr.setValue(std::forward<T>(value));
}
};
//
// this is the implementation of a word
//
struct word_impl {
word_impl(const char *letters) : word_(letters) {
std::cout << "constructed word: " << word_ << std::endl;
}
word_impl(const word_impl &r) : word_(r.word_) {
std::cout << "copied word: " << word_ << std::endl;
}
word_impl(word_impl &&r) noexcept : word_(std::move(r.word_)) {
std::cout << "moved word: " << word_ << std::endl;
}
word_impl &operator=(const word_impl &r) {
if (this != std::addressof(r)) {
word_ = r.word_;
std::cout << "assigned word: " << word_ << std::endl;
}
return *this;
}
word_impl &operator=(word_impl &&r) noexcept {
if (this != std::addressof(r)) {
word_ = std::move(r.word_);
std::cout << "move-assigned word: " << word_ << std::endl;
}
return *this;
}
// some wordy operations
bool comes_before(const word_impl &r) const {
return word_ < r.word_;
}
void setValue(const char* p)
{
std::cout << "value changed from " << word_ << " to " << p << "\n";
word_ = p;
}
// write myself
friend std::ostream &operator<<(std::ostream &os, const word_impl &r) {
return os << std::quoted(r.word_);
}
struct comes_before_op {
bool operator()(const word_impl &l, const word_impl &r) const {
return l.word_ < r.word_;
}
};
std::string word_;
}; // big thing
//
// these are the protocols I want all types of word handles to support
//
template<class Handle>
struct word_impl_protocols
: implement_ostream_protocol<Handle>,
implement_less_than_protocol<Handle, word_impl::comes_before_op> ,
implement_setValue_protocol<Handle>,
boost::less_than_comparable<word_impl_protocols<Handle>>
{
};
auto clone(const word_impl &impl) -> std::unique_ptr<word_impl> {
// clone could if you wished, defer to a virtual clone method
// on word_impl
return std::make_unique<word_impl>(impl);
}
//
// lets make a copyable word that clones its implementation
//
struct unique_word
: word_impl_protocols<unique_word> {
// construct from letters
unique_word(const char *letters) : impl_{std::make_unique<word_impl>(letters)} {}
// let's make it copyable
unique_word(const unique_word &r) : impl_{clone(*r.impl_)} {}
unique_word &operator=(const unique_word &r) {
if (this != std::addressof(r)) {
impl_ = clone(*r.impl_);
}
return *this;
}
// and moveable
unique_word(unique_word &&r) noexcept = default;
unique_word &operator=(unique_word &&r) noexcept = default;
word_impl const &get_reference() const {
return *impl_;
}
word_impl &get_reference() {
return *impl_;
}
// warning - destructive - provides a means to create a
// shared word from a unique_word
auto share() {
return std::shared_ptr<word_impl> {std::move(impl_)};
}
private:
std::unique_ptr<word_impl> impl_;
};
//
// and a word type that shares its implementation
//
struct shared_word
: word_impl_protocols<shared_word> {
shared_word(const char *letters) : impl_{std::make_shared<word_impl>(letters)} {}
shared_word(unique_word &&source) : impl_{source.share()} {}
const word_impl &get_reference() const { return *impl_; }
word_impl &get_reference() { return *impl_; }
std::shared_ptr<word_impl> impl_;
};
int main() {
std::cout << "creating first sentence:\n";
std::vector<unique_word> sentence1 = [] {
std::vector<unique_word> result;
result.emplace_back("abc");
result.emplace_back("def");
result.emplace_back("ghi");
return result;
}();
std::cout << "copying first sentence:\n";
std::vector<unique_word> sentence2 = sentence1;
std::sort(sentence2.begin(), sentence2.end(), std::greater<>());
std::copy(sentence1.begin(), sentence1.end(), std::ostream_iterator<unique_word>(std::cout, ", "));
std::cout << std::endl;
std::copy(sentence2.begin(), sentence2.end(), std::ostream_iterator<unique_word>(std::cout, ", "));
std::cout << std::endl;
std::cout << "converting first sentence to shared words:\n";
std::vector<shared_word> sentence3;
for (auto& unique : sentence1)
{
sentence3.emplace_back(std::move(unique));
}
std::copy(sentence3.begin(), sentence3.end(), std::ostream_iterator<shared_word>(std::cout, ", "));
std::cout << std::endl;
std::cout << "copying sentence of shared words:\n";
auto sentence4 = sentence3;
std::cout << "changing the first word of a shared word sentence:\n";
sentence3.at(0).setValue("xyz");
std::copy(sentence3.begin(), sentence3.end(), std::ostream_iterator<shared_word>(std::cout, ", "));
std::cout << std::endl;
std::copy(sentence4.begin(), sentence4.end(), std::ostream_iterator<shared_word>(std::cout, ", "));
std::cout << std::endl;
}
予想される出力:
creating first sentence:
constructed word: abc
constructed word: def
constructed word: ghi
copying first sentence:
copied word: abc
copied word: def
copied word: ghi
"abc", "def", "ghi",
"ghi", "def", "abc",
converting first sentence to shared words:
"abc", "def", "ghi",
copying sentence of shared words:
changing the first word of a shared word sentence:
value changed from abc to xyz
"xyz", "def", "ghi",
"xyz", "def", "ghi",
あなたは何が必要ですか?概念的には同じ文章の異なるコピーが含まれているかどうか?前者の場合は、ポインタをまったく使用せず、すべてを値で渡します。後者の場合は、文章をより長くし、unique_ptrに格納し、参照または非所有の生ポインタで渡すだけで、範囲内の単語を割り当てることを強くお勧めします。しかし、私はあなたがどんな種類の行動をしたいのか分からないので、私はその質問に答えることができません。 – rubenvb
単語自体を変更していますか?それから、コピーが必要です。そうでなければ(ラップされた) 'shared_ptr ' –
MikeMB