可変長引数テンプレート Variadic Template を Parameter Pack して forward する2020年03月03日 15時15分08秒

emplace_back 等の emplace 系の関数は C++11 から使える様になった可変長引数テンプレートを用いている。可変長引数テンプレートの利点は、複製を避けられること。push_back では、スタック上に一度オブジェクトを生成して、その後複製をして、vector 等に格納していた。それを、vector 等にメモリを割り当てて、そのまま初期化できるのが、emplace 系の関数。

可変長引数テンプレートの表記は大分複雑になったが、基本的にやっているのは、内容物の横流し。使い方は至って簡単で、ほぼ定型。

例として、emplace を単体でどのクラスでも初期化してポインタを返せる様に実装してみた。

#include <memory> // unique_ptr
#include <iostream>

template< typename T, typename... Ts >
T* emplace( Ts&&... args )
{   
    std::unique_ptr< T > value( new T( std::forward< Ts >( args )...
 ) );
    std::cout << *value << std::endl;
    return value.release();
}

int main()
{   
    float *f = emplace< float >( 3.14 );
    int *i = emplace< int >( 3.14 );
    std::string *s = emplace< std::string >( 3, 'a' );
    // ここのメモリリークは無視。
}
emplace は unique_ptr を用いて、メモリの割当と、コンストラクタの呼出を行って、生成されたオブジェクトを返す。任意のオブジェクトを初期化でき、また任意の数の引数を渡せる。

実行例。

% c++ -std=c++11 emplace.cpp
% ./a.out
3.14
3
aaa

次回