Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

就地創建

使用包裝器和容器的一個常見問題是,它們通常會有一個接口提供一個操作,將所含對像初始化或賦值為另一個對象的拷貝。這不僅要求底層的類型是 可複製構造的,而且還要求一個完全構造的對象,該對像通常是臨時的,僅用作複製的來源: 

struct X
{
    X ( int, std:::string ) ;
} ;

class W
{
    X wrapped_ ;

    public:

    W ( X const& x ) : wrapped_(x) {}
} ;

void foo()
{
    // 創建臨時對像
W ( X(123,"hello") ) ; }

解決這一問題的一種方法是,提供在容器的存儲中直接構造所含對象的支持。這樣一來,用戶只需要將相關參數提供給構造函數,用於所含對象的構造。

class W
{
    X wrapped_ ;

    public:

    W ( X const& x ) : wrapped_(x) {}
    W ( int a0, std::string a1) : wrapped_(a0,a1) {}
} ;

void foo()
{
    // 就地創建所含對象,不再需要創建臨時對像
W (123,"hello") ; }

這種方法的限制在於,它不適用於帶有多個構造函數的被包裝對象,也不適用於對構造函數重載不知情的泛型代碼。

在本庫中,解決的方法是 InPlaceFactoriesTypedInPlaceFactories 家族。這些工廠是一族類,這些類封裝了不同參數數量的構造函數參數,提供一個方法來構造給定類型的一個對象,構造時使用這些被封裝的參數,並通過 placement new 在用戶指定的地址進行構造。

例如,這個類族中的其中一個類如下:

template<class T,class A0, class A1>
class TypedInPlaceFactory2
{
    A0 m_a0 ; A1 m_a1 ;

    public:

    TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}

    void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
 } ;

一個包裝類可以這樣來使用它:

class W
{
    X wrapped_ ;

    public:

    W ( X const& x ) : wrapped_(x) {}
    W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
} ;

void foo()
{
    // 通過 TypedInPlaceFactory 就地構造被包裝對象。無需創建臨時對象。
W ( TypedInPlaceFactory2<X,int,std::string&rt(123,"hello")) ; }

這些工廠類被分為兩組:

在每一組中,所有類族成員僅在可接受的參數數量上有所不同。

本庫還提供了一組重載的模板函數來構造這些工廠類,從而無需給定模板參數:

template<class A0,...,class AN>
InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ;

template<class T,class A0,...,class AN>
TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ;

就地創建可以被包裝器和用戶泛型地使用,如下:

class W
{
    X wrapped_ ;

    public:

    W ( X const& x ) : wrapped_(x) {}

    template< class InPlaceFactory >
    W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }

} ;

void foo()
{
    // 通過 InPlaceFactory 就地構造被包裝的對象。無需創建臨時對象。
W ( in_place(123,"hello") ) ; }

這些工廠類在頭文件 in_place_factory.hpptyped_in_place_factory.hpp 中實現。


PrevUpHomeNext