2013-03-08 96 views
0

我想做一個模板類作爲佔位符類,它可以容納類似的東​​西,字符串和類型的T對象。下面是我寫的相同的代碼。C++使模板類作爲另一個類中的佔位符

#include <iostream> 
#include <string> 
#include <map> 

using namespace std; 

//A class which act as placeholder to hold 
//unknown object. Something similar as Object 
//in Java 
template <typename T> 
class Genric 
{ 
    public: 
     map<string, T> addP; //This will be placeholder for time 
     // being. 
}; 

class A 
{ 
    public: 
     Genric t1; //Have object of Genric class so that we can 
     // access the member variable in future. 
     void foo() 
     { 
      cout<<"Calling foo"<<endl; 
     } 
}; 

int main() 
{ 
    A a1; 
    a1.foo(); 
} 

但是,當我試圖編譯我得到以下錯誤。

$ g++ tempClass.cxx 
tempClass.cxx:21:9: error: invalid use of template-name 'Genric' without an argument list 

上面Genric類的目的只是充當將來可以填充的其中一個成員變量的佔位符類。 那麼有沒有一種方法可以寫出這樣的Genric類。

回答

2

你需要的東西像boost::any

map<string, boost::any> anywayzz; 

您可以將任何對象存儲在它。您不需要Genric類模板。

如果你不使用boost,那麼你可以自己實現any。尋找其實施,或類型擦除,在這個網站上。你一定會有一些想法。從這裏開始:

2

您正在定義Genric爲模板類,但隨後試圖初始化t1沒有給人一種類型吧。那是你得到的錯誤。嘗試例如:

Genric<int> t1; 

或者,如果你正在尋找一個真正運行時一般,看看的boost ::任何

2

在編譯程序之前,模板是「通用」的。此時,必須讓編譯器知道它需要處理哪些類型。

如果您希望某個可以包含編譯時未知(更好:尚未知道)類型模板的東西不是解決方案。由於實際類型只是在運行時才知道,所以你必須轉向最終包裝在「處理程序」中的基於運行時的多態(繼承自多態基)。

從本質上講,您需要一個基本的函數,它允許您檢查類型以及實現該函數的泛型派生類,以適合all類型的方式。

boost :: any可以是一個實現,但可以有更簡單的方法,特別是考慮到「允許發現運行時類型的函數」不超過... dynamic_cast

可以使COMETO這樣

#include <memory> 

class any_value 
{ 
    template<class T> 
    class wrapper; //see below 

    class common_base 
    { 
    public: 
     virtual ~common_base() {} //this makes the type polymorphic 

     template<class T> 
     T* has_value() 
     { 
      auto* ptr = dynamic_cast<wrapper<T>*>(this); 
      return ptr? &ptr->m: nullptr; 
     } 
    }; 

    template<class T> 
    class wrapper: public common_base 
    { 
    public: 
     wrapper() :m() {} 
     wrapper(const T& t) :m(t) {} 

     T m; 
    }; 

    std::unique_ptr<common_base> pb; 

public: 

    any_value() {} 

    template<class T> 
    any_value(const T& t) :pb(new wrapper<T>(t)) {} 

    template<class T> 
    any_value& operator=(const T& t) 
    { pb = std::unique_ptr<common_base>(new wrapper<T>(t)); return *this; } 

    any_value(any_value&&) =default; 
    any_value& operator=(any_value&&) =default; 

    //NOW THE GETTERS 
    template<class T> 
    T* get() const //nullptr if not holding a T* 
    { return bool(pb)? pb->has_value<T>(): nullptr; } 

    template<class T> 
    bool get(T& t) 
    { 
     T* pt = get<T>(); 
     if(pt) t = *pt; 
     return bool(pt); 
    } 
}; 

#include <iostream> 
#include <string> 

int main() 
{ 
    any_value a(5), b(2.7192818), c(std::string("as a string")); 
    int vi=0; double vd=0; std::string vs; 

    if(!a.get(vi)) vi=0; //will go 
    if(!a.get(vd)) vd=0; //will fail 
    if(!a.get(vs)) vs.clear(); //will fail 
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n"; 
    if(!b.get(vi)) vi=0; //will fail 
    if(!b.get(vd)) vd=0; //will go 
    if(!b.get(vs)) vs.clear(); //will fail 
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n"; 
    if(!c.get(vi)) vi=0; //will fail 
    if(!c.get(vd)) vd=0; //will fail 
    if(!c.get(vs)) vs.clear(); //will go 
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n"; 
} 

解決以下阿比納夫評論:

由於C++類型系統是靜態的,你不能-in中普通反序列化一個「未知「,除非您首先反序列化可以是」已知「的內容。爲此,首先需要一種將C++類型(不是對象)表示爲可識別值(類型uid)的方法,以及創建用於這些「值」的包裝器的「工廠」。

保存時,您只需保存 uid,然後通過common_base虛函數詢問是否保存包裝的值。 在裝載時,首先加載UID,比創建具有適當類型一個新的包裝(見後),比通過common_base虛函數加載值。

要建立一個適當的包裝,你需要的UID-S實現這一創建類型UID相關的包裝函數映射表。 對於需要序列化/反序列化的所有類型,此表必須進行預初始化。

但這樣的長走你原來的問題,不談論序列化/反序列化。

如果問題是「系列化」,在「類型擦除」不是一個完整的解決方案。你應該更多地關注「工廠模式」。併發布更適合該論點的另一個問題。

+0

看來這可以工作,但有這樣的佔位符類的最終目標是,使用S11N ::反序列化,可以在運行時,但如果未知的東西來,然後如何照顧與做一個基本類型反序列化反序列化對象以上方法。 – Abhinav 2013-03-08 09:56:06

+0

@Abhinav:看到編輯。 – 2013-03-08 11:18:12

相關問題