2011-12-23 22 views
9

Rasgele nesneleri std :: string ile saklayabilen bir yapılandırma yöneticisi sınıfı oluşturmaya çalışıyorum.Özet bir temel sınıfta şablon işlevine sahip olmanın herhangi bir yolu var mı?

benim arayüzüne (soyut temel sınıf) Benim başlangıç ​​fikri bu

class ConfigurationManager 
{ 
public: 
    static boost::shared_ptr<ConfigurationManager> create(); 

    template<typename T> 
    virtual T getOption(const std::string& name) = 0; 
}; 

(tabii bu korkunç eksiktir) Ama sonra benim derleyici şablon sanal olamayacağını işaret (ve sonra fark ettim oldu ki ben zaten ihraç edilmiş şablonlar olamaz).

Dahili olarak boost :: any's (hemen hemen bir çalışma zamanı kontrol edilmiş void *) kullanıyor olacağım, ancak boost'umu herhangi bir şekilde göstermek istemiyorum.

Bu konuda gitmenin en iyi yolu ne olurdu?

+1

Tam olarak ne için gitmek için? –

+0

@Oli Sorgumda gönderdiğim sözdizimsel imkansız arabirimi simüle etmek için. – Lalaland

+0

Yani gerçekten mümkün olmasalar bile, polimorf fonksiyon şablonları yapmak istersiniz? –

cevap

7

boost::any numaralı ve sanal olmayan, soyut olmayan, genel şablon işlevini döndürerek, arabiriminizin kullanıcılarından gizlemek için korunan sanal bir soyut işlev oluşturun.

class ConfigurationManager { 
protected: 
    virtual boost::any getOptionProtected(const std::string& name) = 0; 
public: 
    static boost::shared_ptr<ConfigurationManager> create(); 
    template<typename T> T getOption(const std::string& name) { 
     return boost::any_cast<T>(getOptionProtected(name)); 
    } 
}; 
+0

Bu, boost :: any_cast (getOptionProtected (name)) olmalıdır; – Xeo

+0

@Xeo Düzeltme için teşekkürler! (Sadece bir satırdan daha önce hiç güç kullanmadığımı söyleyebilirsin). – dasblinkenlight

+0

Neredeyse bununla bitti. – Lalaland

4

Alternatif bir yaklaşım, ConfigurationManager için türetilmiş bir tür adı geçmek olacaktır:

template<typename Derived> 
class ConfigurationManager 
{ 
    public: 
    static boost::shared_ptr<ConfigurationManager> create(); 

    template<typename T> 
    T getOption(const std::string& name) 
    { 
    // call Derived::getOption 
    return static_cast<Derived*>(this)->getOption(name); 
    } 
}; 

Foo sonra böyle tanımlanacaktır türevi türü:

class Foo : public ConfigurationManager<Foo> 
{ 
    template<typename T> 
    T getOption(const std::string& name) 
    { 
    // do something Foo-specific here 
    } 
}; 

uç Sonuç soyut bir sanal işleve benzer bir şeydir. Bu deyim curiously recurring template pattern olarak adlandırılır.

+1

Bunun eski olduğunu biliyorum, ancak bu CRTP kullanımında ConfigurationManager sınıfının amacı nedir? Foo'yu depolamak için bu tipi kullanamayız. – Constantin

1

Ben boost::any senin için ne yaptığını bilmiyorum, ama bir kenara (sadece, sanırım) seçenekleridir bundan ya 1) Bir şablon sınıfı ConfigurationManager olun veya 2) ConfigurationManager::getOptionolmayan-Sanal yapmak ancak kullanmayın türetilmiş sınıflarınızda istediğiniz işlevi yöneten, şablon olmayan sanal işlev (getOption içinde çağrılır). Ayrıca, (sanal olmayan) getOption'un amaçlanan işlevini belirten bir nesneye bir işaretçi dahil olmak üzere 2) üzerinde varyantlar da vardır. Bu amaç, temel olarak bir kalıtım hiyerarşisinin bir parçası olan bir sınıfın örneği olacaktır - Strateji modeli temel olarak. Gerçi daha karmaşık görünüyor. Bu hemen hemen tüm yapabileceğiniz olduğunu düşünüyorum neden Böylece temelde this SO thread için

class ConfigurationManager 
{ 
    public: 
     ... 
     template<typename T> 
     getOption(...); 
    private: 
     virtual getOptionSpecial(...) = 0; //Called within getOption 
}; 

üst cevap öneriyorum (kısmen) 'dir.

İlgili konular