Skip to content

Latest commit

 

History

History
95 lines (73 loc) · 2.67 KB

064-cpp17-lib-misc-map.md

File metadata and controls

95 lines (73 loc) · 2.67 KB

mapとunordered_mapの変更

mapunordered_mapに、try_emplaceinsert_or_assignという2つのメンバー関数が入った。このメンバー関数はmulti_mapunordered_multi_mapには追加されていない。

try_emplace

template <class... Args>
pair<iterator, bool>
try_emplace(const key_type& k, Args&&... args);

template <class... Args>
iterator
try_emplace(
    const_iterator hint,
    const key_type& k, Args&&... args);

従来のemplaceは、キーに対応する要素が存在しない場合、要素がargsからemplace構築されて追加される。もし、キーに対応する要素が存在する場合、要素は追加されない。要素が追加されないとき、argsがムーブされるかどうかは実装定義である。

int main()
{
    std::map< int, std::unique_ptr<int> > m ;

    // すでに要素が存在する
    m[0] = nullptr ;

    auto ptr = std::make_unique<int>(0) ;
    // emplaceは失敗する
    auto [iter, is_emplaced] = m.emplace( 0, std::move(ptr) ) ;

    // 結果は実装により異なる
    // ptrはムーブされているかもしれない
    bool b = ( ptr != nullptr ) ;
}

この場合、実際にmapに要素は追加されていないのに、ptrはムーブされてしまうかもしれない。

このため、C++17では、要素が追加されなかった場合argsはムーブされないことが保証されるtry_emplaceが追加された。

int main()
{
    std::map< int, std::unique_ptr<int> > m ;

    // すでに要素が存在する
    m[0] = nullptr ;

    auto ptr = std::make_unique<int>(0) ;
    // try_emplaceは失敗する
    auto [iter, is_emplaced] = m.try_emplace( 0, std::move(ptr) ) ;

    // trueであることが保証される
    // ptrはムーブされていない
    bool b = ( ptr != nullptr ) ;
}

insert_or_assign

template <class M>
pair<iterator, bool>
insert_or_assign(const key_type& k, M&& obj);

template <class M>
iterator
insert_or_assign(
    const_iterator hint,
    const key_type& k, M&& obj);

insert_or_assignkeyに連想された要素が存在する場合は要素を代入し、存在しない場合は要素を追加する。operator []との違いは、要素が代入されたか追加されたかが、戻り値のpairboolでわかるということだ。

int main()
{
    std::map< int, int > m ;
    m[0] = 0 ;

    {
        // 代入
        // is_insertedはfalse
        auto [iter, is_inserted] = m.insert_or_assign( 0, 1 ) ;
    }

    {
        // 追加
        // is_insertedはtrue
        auto [iter, is_inserted] = m.insert_or_assign( 1, 1 ) ;
    }
}