2013-01-17 17 views
6

Nói rằng tôi có các loại sau:Làm thế nào để tăng chuỗi đúng cách :: mpl :: inherit_linearly và boost :: mpl :: kế thừa để giữ chỗ có thể được giải quyết?

template 
< 
    class T, 
    template <class> class Storage 
> 
struct AbstractFactoryUnit 
{ 
    virtual ~AbstractFactoryUnit() {} 
    virtual typename Storage<T>::StoredType doCreate(Storage<T>) = 0; 
}; 

template 
< 
    class TypeSequence, 
    template <class> class ProductStorage, 
    template <class, template <class> class> class Unit = AbstractFactoryUnit 
> 
struct AbstractFactory 
    : boost::mpl::inherit_linearly 
     < 
      TypeSequence, 
      boost::mpl::inherit 
      < 
       boost::mpl::_1, 
       Unit< boost::mpl::_2, ProductStorage > 
      > 
     >::type 
{ 
    typedef TypeSequence Products; 

    template <class T> 
    auto create() -> typename ProductStorage<T>::StoredType 
    { 
     Unit< T, ProductStorage >& unit = *this; 
     unit.doCreate(ProductStorage<T>()); 
    } 
}; 

Bây giờ tôi muốn thực hiện le AbstractFactory ...

Một số loại lol:

struct Foo {}; 
struct Bar {}; 
struct Baz {}; 

Một lol bộ nhớ :

template <class T> 
struct RawPointerStorage 
{ 
    typedef T* StoredType; 
}; 

và cuối cùng là thực hiện:

struct FooBarBaz 
    : AbstractFactory< boost::mpl::set< Foo, Bar, Baz >, RawPointerStorage > 
{ 
    A* doCreate(RawPointerStorage<Foo>) override 
    { 
     return new A; 
    } 

    B* doCreate(RawPointerStorage<Bar>) override 
    { 
     return new B; 
    } 

    C* doCreate(RawPointerStorage<Baz>) override 
    { 
     return new C; 
    } 
}; 

Thật không may, trình biên dịch phàn nàn:

1>C:\Libs\boost\boost_1_51_0\boost/mpl/aux_/preprocessed/plain/inherit.hpp(20): error C2500: 'boost::mpl::inherit2<T1,T2>' : 'AbstractFactoryUnit<T,ProductStorage>' is already a direct base class 
1>   with 
1>   [ 
1>    T1=AbstractFactoryUnit<boost::mpl::_2,RawPointerStorage>, 
1>    T2=AbstractFactoryUnit<boost::mpl::_2,RawPointerStorage> 
1>   ] 
1>   and 
1>   [ 
1>    T=boost::mpl::_2, 
1>    ProductStorage=RawPointerStorage 
1>   ] 

Tôi là một chút bối rối vì nó chỉ cần biên dịch tốt khi AbstractFactoryUnit chỉ chấp nhận một tham số mẫu. Tôi đoán là trình biên dịch không thể "giải quyết" trình giữ chỗ thứ hai, nhưng tôi nên thừa nhận tôi không biết tại sao - vì tôi không biết rõ cách tăng giá gọi apply trên trình giữ chỗ.

Tôi sử dụng VS2012 với vc100 hoặc vc110.

Bất kỳ ý tưởng nào? (vâng, tôi đang chơi với AbstractFactory được mô tả trong hiện đại C++ thiết kế)

EDIT: Cuối cùng tôi quyết định cung cấp toàn bộ AbstractFactory mã của tôi mà không cần cải trang trong cả hai câu hỏi của tôi và câu trả lời của tôi.

Trả lời

1

Tôi không biết chính xác lý do - trong ngữ cảnh này-- trình giữ chỗ thứ hai không thể "mở rộng" nhưng tôi phát hiện ra rằng việc đóng biểu thức boost::mpl::inherit đã giải quyết được sự cố của tôi.

Vì vậy, đây bạn đang có, AbstractFactory này trong một nutshell:

Chúng tôi đóng gói thực hiện trong một không gian tên Impl:

namespace Impl 
{ 

    template 
    < 
     class TypeSequence, 
     template <class> class ProductStorage, 
     template <class, template <class> class> class Unit 
    > 
    struct AbstractFactory 
    { 
    private: 
     template <class T, class U> 
     struct Inherit : boost::mpl::inherit< T, Unit< U, ProductStorage > > 
     {}; 

    public: 
     typedef typename boost::mpl::inherit_linearly 
          < 
           TypeSequence, 
           // the trick is on the following line 
           Inherit< boost::mpl::_1, boost::mpl::_2 > 
          > 
          ::type Type; 
    }; 

} // namespace Impl 

và chúng tôi xuất phát từ nó như vậy:

template 
< 
    class TypeSequence, 
    template <class> class ProductStorage = RawPointerStorage, 
    template <class, template <class> class> class Unit = AbstractFactoryUnit 
> 
struct AbstractFactory 
    : Impl::AbstractFactory< TypeSequence, ProductStorage, Unit >::Type 
{ 
    typedef TypeSequence Products; 

    template <class T> 
    auto create() -> typename ProductStorage<T>::StoredType 
    { 
     Unit< T, ProductStorage >& unit = *this; 
     return unit.doCreate(ProductStorage<T>()); 
    } 
}; 
Các vấn đề liên quan