在編譯程序之前,模板是「通用」的。此時,必須讓編譯器知道它需要處理哪些類型。
如果您希望某個可以包含編譯時未知(更好:尚未知道)類型模板的東西不是解決方案。由於實際類型只是在運行時才知道,所以你必須轉向最終包裝在「處理程序」中的基於運行時的多態(繼承自多態基)。
從本質上講,您需要一個基本的函數,它允許您檢查類型以及實現該函數的泛型派生類,以適合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相關的包裝函數映射表。 對於需要序列化/反序列化的所有類型,此表必須進行預初始化。
但這樣的長走你原來的問題,不談論序列化/反序列化。
如果問題是「系列化」,在「類型擦除」不是一個完整的解決方案。你應該更多地關注「工廠模式」。併發布更適合該論點的另一個問題。
看來這可以工作,但有這樣的佔位符類的最終目標是,使用S11N ::反序列化,可以在運行時,但如果未知的東西來,然後如何照顧與做一個基本類型反序列化反序列化對象以上方法。 – Abhinav 2013-03-08 09:56:06
@Abhinav:看到編輯。 – 2013-03-08 11:18:12