One-Phase Construction

25
emplace、使ってますか? one-phase construction とは? one-phase construction 教の夢 . . One-Phase Construction hatsusato 京都大学理学部 2 回生 2013 10 3 1 / 23

Transcript of One-Phase Construction

Page 1: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.

...... One-Phase Construction

hatsusato

京都大学理学部 2回生

2013年 10月 3日

1 / 23

Page 2: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. 自己紹介

@hatsusato のプロフィール理学部数学系志望

C++一筋アニメ好き作画オタク

2 / 23

Page 3: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. 目次

...1 emplace、使ってますか?

...2 one-phase constructionとは?

...3 one-phase construction教の夢

3 / 23

Page 4: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. emplace、使ってますか?

...1 emplace、使ってますか?

...2 one-phase constructionとは?

...3 one-phase construction教の夢

4 / 23

Page 5: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. emplace

C++11以降、標準コンテナの多くが emplaceやemplace backといった名前のメンバ関数を持つようになった。これらはコンテナに要素を追加するメンバ関数なのだが、一体どういう機能を持っているのか。同じく要素を追加する insertや push backとは何が違うのか。// 従 来 の 要 素 を 追 加 す る メ ン バ 関 数iterator insert(const_iterator pos , const T& value);

void push_back(const T& value);

// e m p l a c eのシグネチャtemplate <class ... Args >

iterator emplace(const_iterator pos , Args &&... args);

// e m p l a c e _ b a c kのシグネチャtemplate <class ... Args >

void emplace_back(Args &&... args);

5 / 23

Page 6: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. emplace

insertや push backは T型のオブジェクトを引数にとる。新しくオブジェクトを作って追加したい時は、一時オブジェクトをコンストラクトして引数に渡してやる必要がある。emplaceや emplace backはその代わりに Tのコンストラクタ引数を受け取り、オブジェクトのコンストラクトをコンテナへの追加と同時に行うことができる。// 従 来 の 要 素 を 追 加 す る メ ン バ 関 数iterator insert(const_iterator pos , const T& value);

void push_back(const T& value);

// e m p l a c eのシグネチャtemplate <class ... Args >

iterator emplace(const_iterator pos , Args &&... args);

// e m p l a c e _ b a c kのシグネチャtemplate <class ... Args >

void emplace_back(Args &&... args);

6 / 23

Page 7: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. emplace

struct X {

X(int) {

std::cout << "Constructor." << std::endl;

}

X(const X&) {

std::cout << "Copy constructor." << std::endl;

}

X(X&&) {

std::cout << "Move constructor." << std::endl;

}

};

int main() {

std::vector <X> vec;

vec.reserve (2);

vec.push_back(X(42));

// Constructor.

// Move constructor.

vec.emplace_back (42);

// Constructor.

return 0;

}

7 / 23

Page 8: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. emplace

insertや push backの場合、コンストラクタ 1回とコピーコンストラクタ 1回とが実行される。

C++11以降はムーブの仕組みがあるため、T型がMoveConstructableなら、コンストラクタ 1回とムーブコンストラクタ 1回とが実行される。

emplaceや emplace backの場合、コンストラクタ 1回のみが実行される。

std::vector <X> vec;

vec.reserve (2);

vec.push_back(X(42));

// Constructor.

// Move constructor.

vec.emplace_back (42);

// Constructor.

8 / 23

Page 9: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. piecewise construct

C++11から新しく std::piecewise construct t型のstd::piecewise constructという constexpr定数が追加され、それに伴い std::pairに新しいコンストラクタが追加されました。std::piecewise constructはタグとして機能し、以降の引数の std::tupleを firstと secondのコンストラクタ引数として利用することを明示します。

このタグがないと tupleの pairが作れない。

// p a i r の 新 し い コ ン ス ト ラ ク タ の シ グ ネ チ ャtemplate <class ... Args1 , class ... Args2 >

pair(std:: piecewise_construct_t , // タ グstd::tuple <Args1...> first_args , // 引 数 の tuple

std::tuple <Args2...> second_args ); // 引 数 の tuple

9 / 23

Page 10: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. piecewise construct

// std:: piecewise_constructの利用例struct Unmovable {

template <class ... Args >

Unmovable(Args ...) {}

Unmovable(Unmovable &&) = delete;

Unmovable& operator =( Unmovable &&) = delete;

};

std::map <std::string , Unmovable > map;

// std::map:: value_typeはstd ::pair <const Key , T>

// e m p l a c eは v a l u e _ t y p eのコンストラクタ引数を引数に取るmap.emplace(std:: piecewise_construct ,

// 引 数 を t u p l eにして転送std:: forward_as_tuple (10, ’a’),

std:: forward_as_tuple (1, 2, 3, 4));

10 / 23

Page 11: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. one-phase constructionとは?

...1 emplace、使ってますか?

...2 one-phase constructionとは?

...3 one-phase construction教の夢

11 / 23

Page 12: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. one-phase constructionとは?

http://bit.ly/95tgcT →http://www.boost.org/doc/libs/1_54_0/libs/utility/in_place_factories.html

http://bit.ly/9r8QCH →

http://www.boost.org/doc/libs/1_54_0/libs/serialization/doc/serialization.html#const

12 / 23

Page 13: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. one-phase constructionとは?

one-phase constructionとは、コンストラクト時に「コンストラクタ引数のオブジェクト」の代わりに「引数のオブジェクトのコンストラクタ引数」を受け取り、適切に引数の転送をすることでコンストラクトを遅延し、余分な一時オブジェクトの生成を抑制する機構のことである。

先の emplaceと piecewise constructはその一例。

これにより従来潜在的に存在した余分な実行時コスト (中間オブジェクトの生成と破棄)を削減し、さらに高速なコードの生成が可能になる。

13 / 23

Page 14: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. ムーブがあるんだし、それで十分じゃないの?

確かに、ほとんどの場合、ムーブコンストラクタは十分に高速なので、そのムーブコンストラクタ呼び出しを省略したところで実行時速度はあまり変わらない。

しかし、ムーブが高速でないクラス (ムーブ=コピーかつコピーが重たいクラスなど)や、Copyableでも Movableでもないクラス (mutexなど)も高速に構築できる点でone-phase constructionは優れている。one-phase constructionはコピーおよびムーブを行わないので、オブジェクトのアドレスは変化しない。したがってオブジェクトのアドレスの不変性が重要なmutexや atomicオブジェクトでもコンテナに格納することができる。

14 / 23

Page 15: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. ムーブがあるんだし、それで十分じゃないの?

確かに、ほとんどの場合、ムーブコンストラクタは十分に高速なので、そのムーブコンストラクタ呼び出しを省略したところで実行時速度はあまり変わらない。

しかし、ムーブが高速でないクラス (ムーブ=コピーかつコピーが重たいクラスなど)や、Copyableでも Movableでもないクラス (mutexなど)も高速に構築できる点でone-phase constructionは優れている。one-phase constructionはコピーおよびムーブを行わないので、オブジェクトのアドレスは変化しない。したがってオブジェクトのアドレスの不変性が重要なmutexや atomicオブジェクトでもコンテナに格納することができる。

14 / 23

Page 16: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. ムーブがあるんだし、それで十分じゃないの?

struct Unmovable {

Unmovable () = default;

Unmovable(Unmovable &&) = delete;

Unmovable& operator =( Unmovable &&) = delete;

};

struct HeavyToMove {

HeavyToMove () = default:

HeavyToMove(HeavyToMove &&) = default;

HeavyToMove& operator =( HeavyToMove &&) = default;

HeavyToCopy data [1024]; // コ ピ ー が 重 た い ク ラ ス};

// Unmovableはstd :: l i s tで保持する必要があるstd::list <Unmovable > list;

list.emplace_back (); // ム ー ブ し て い な い の で 構 築 可 能std::vector <HeavyToMove > vector;

vector.emplace_back (); // ム ー ブ し て い な い の で 高 速

15 / 23

Page 17: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. そんなに速くなってどうするの?

C++erにそんなことを言ってはいけません。速ければ速い方がいいのです。

16 / 23

Page 18: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. そんなに速くなってどうするの?

C++erにそんなことを言ってはいけません。速ければ速い方がいいのです。

16 / 23

Page 19: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. one-phase construction教の夢

...1 emplace、使ってますか?

...2 one-phase constructionとは?

...3 one-phase construction教の夢

17 / 23

Page 20: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. 構築と初期化の一体化

引数の tupleから one-phaseでオブジェクト構築できるなら、それを入れ子にすることでより複雑なオブジェクトでも one-phaseで構築できるのでは?つまり、引数リストの木をコンストラクタ引数にとることで、一瞬でオブジェクトを構築できるのでは?

18 / 23

Page 21: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. 構築と初期化の一体化

// こ ん な 感 じstruct A {};

struct B {};

struct C {

C(const A&, const B&) {}

};

struct D {};

struct E {

E(const D&) {}

};

struct F {

F(const E&) {}

};

struct X {

X(const C&, const F&) {}

};

X x{{{}, {}}, {{{}}}}; // R V Oが働いている?// X x{C{A{}, B{}}, F{E{D{}}}};

19 / 23

Page 22: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. 構築と初期化の一体化

one-phase constructionは無条件に利用できるわけではなく、標準の emplaceや piecewise constructをタグに取るコンストラクタと同様の実装を、ユーザ定義クラスのコンストラクタでも行う必要がある。可変長テンプレートと Perfect Forwardingのある現在においてその実装はそれほど困難ではないが、すべてのユーザ定義クラスにわたってそのようなコンストラクタを提供するのは大きなコストである。

もし、言語機能として one-phase constructionをユーザ定義クラスにおいても非侵入的に提供することが出来れば、オブジェクトの構築と初期化が一体化したより最適化された理想郷の恩恵を、より広い範囲にわたって受けることができるだろう。

20 / 23

Page 23: One-Phase Construction

emplace、使ってますか?one-phase constructionとは?one-phase construction教の夢

.. 構築と初期化の一体化

21 / 23

Page 24: One-Phase Construction

参考文献

.. 参考文献

.N3059 - Togetter........http://togetter.com/li/17236

.One-Phase Construction入門~ Constructor run once. -野良 C++erの雑記帳........http://d.hatena.ne.jp/gintenlabo/20101210/1291914878

.rvalue-referenceで one-phase construction -野良 C++erの雑記帳........http://d.hatena.ne.jp/gintenlabo/20101211/1292088788

22 / 23

Page 25: One-Phase Construction

参考文献

.. 参考文献

.pairの piecewise construction - Faith and Brave - C++で遊ぼう........http://d.hatena.ne.jp/faith_and_brave/20100428/1272422821

.c++ - When to make a type non-movable in C++11? - StackOverflow..

......http://stackoverflow.com/questions/14302834/

when-to-make-a-type-non-movable-in-c11

23 / 23