1

で移動セマンティクスを実装する適切な方法はoperator+? 同様に、それがどのように機能するのstd::stringですか?

私は次のことを試みましたが、それを行うためのよりエレガントでおそらくより正しい方法があることを望んでいました:

class path
{
    std::vector<std::string> path_;
public:

    path& path::operator+=(const path& other)
    {
        path_.insert(std::begin(path_), std::begin(other.path_), std::end(other.path_));
        return *this;
    }

    path& path::operator+=(path&& other)
    {
        path_.insert(std::begin(path_), std::make_move_iterator(std::begin(other.path_)), std::make_move_iterator(std::end(other.path_)));
        return *this;
    }
};

template<typename L, typename R>
typename std::enable_if<std::is_convertible<path, L>::value, path>::type operator+(const L& lhs, const R& rhs)
{
    auto tmp = std::forward<L>(lhs);
    tmp     += std::forward<R>(rhs);
    return tmp;
}
4

1 に答える 1

2

あまりにも複雑です。:)あなたがすでに従うべきだった規則をただ守ってください:

  • のlhsをoperator+値で取る
  • lhsoperator+の観点から実装するoperator+=

これは、コピーの省略とRVOのために、C++03ではすでに当てはまりました。経験則:とにかくコピーを作成する場合は、パラメーターで作成してください。

それを念頭に置いて:

#include <iterator>
#include <utility>

class path
{
    std::vector<std::string> path_;
public:

    path& operator+=(path other)
    {
        auto op_begin = std::make_move_iterator(std::begin(other.path_));
        auto op_end = std::make_move_iterator(std::end(other.path_));
        path_.reserve(path_.size() + other.path_.size());
        path_.insert(std::end(path_), op_begin, op_end);
        return *this;
    }
};

path operator+(path lhs, path rhs)
{
  return std::move(lhs += std::move(rhs));
}

これが最適な形式です。また、パスを追加operator+=するのではなく、実際に追加するように変更したことに注意してください(それがあなたの考えであったことを願っています。そうでない場合は、もう一度変更してください)。std::begin(path_)

また、rhsoperator+operator+=valuesを作成し、それらを移動しました。std::make_move_iterator素晴らしいユーティリティでもあります。名前が示すように、コピーする代わりに、ポイントされた要素を移動します。これは本当に速くなるはずです。

std::move別のバージョンは、 inのイテレータバージョンを使用することoperator+=です。

path& operator+=(path other)
{
    path_.reserve(path_.size() + other.path_.size());
    std::move(other.begin(), other.end(), std::back_inserter(path_));
    return *this;
}
于 2011-12-31T11:11:00.320 に答える