2012-01-16 31 views
1

我正在爲我們在其他代碼中定義的一堆類編寫泛型包裝類。我試圖弄清楚C++中是否有方法來編寫一個可以將模板參數存儲爲變量的模板類。下面是我想看到什麼工作的一個例子:C++商店模板參數作爲變量

template < class C > class generic { 
    public: 
     C obj; // used for custom type processing 

     template < class T > T other; // <- changeable variable (or something) 

     template < class T > setOther() { // Function to change variable 
      // code to change variable type, or set type 
     } 

     void doSomethingWithOther() { 
      // do some processing for other, like call 
      // specific member function or something 
      (((other*)obj)->*SomeGenericMethod)() 
     } 
} 

int main(int argc, char **argv) { 
    Bar bObj; 
    generic<Foo> fObj; 
    fObj.setOther<Bar>(); 
    fObj.doSomethingWithOther(); 
    return 0; 
} 

我知道上面的代碼將不能編譯的原因有很多,但我的問題更多的是關於功能。有什麼方法可以將模板參數存儲爲一個變量(或使用函數或其他東西),然後稍後可以將它用作類型說明符?如果沒有一個標準的方式,來自SO社區的任何想法都可能導致我期望的結果?

請不要升壓或其他第三方庫,我試圖保持它作爲「STL」(C99)儘可能。

另一個想法我是使用默認的專業化:

template < class C, class T = void* > class generic { 
    public: 
     C obj; 
     T other; 
     // ... more code 
} 

,但在那種情況下,假設我們有以下幾點:

class Test1 { 
    public: 
     generic<Foo> *G1; 
     generic<Foo, Bar> *G2; 
}; 

如果我想以後改變G1的類型做一些其他處理,我可以這樣說:

G1 = new generic<Foo, Bar>(); // compile error, different types 

但是,這會導致編譯錯誤,因爲指向的兩種類型是不同類型的(G1是generic<C>類型,另一種類型是generic< C, T >,即使模板類T默認爲void*

對不起,很長一段文章,我想盡可能清楚我的意圖與此代碼。同樣,請隨時糾正我在我上面的任何言論(長期=對我來說較少的大腦活動)

在此事先感謝您的任何幫助。

編輯1:

爲了澄清,所述other數據成員是僅僅有顯示我想該部件保持一個類的類型。這是因爲我們的代碼有其他類的成員調用實例化成員函數。如果我要調用一個不同類的成員函數,我會得到一個編譯錯誤。

不幸的是我不能使用任何C++ 0x功能,因爲我們的嵌入式編譯器比較老,不支持0x功能集。否則,這將是明顯的解決方案。

我基本上不必建立在委託類型系統,以使得實例化的類可以自身內和稱爲成員函數調用從其他實例化類的成員將具有存儲空間,並獲得了this指針

例如:

class Foo { 
    public: 
     Delegate other; 
} 

class Bar { 
    public: 
     void SomeFunction() { 
      std::cout << "hello from Bar::SomeFunction, data = " << data << std::endl; 
     } 

     int data; 
} 

int main() { 
    Foo F; 
    Bar B; 
    B.data = 10; 
    F.other = Delegate::attach<Bar>(&Bar::SomeFunction, &B); 
    // Delegate::attach is defined as 
    // template < class T > Delegate attach(void (T::*fnPtr)(void*), T *obj) 
    F.other(); 
} 

在上面的例子中Delegate類的void operator()()然後調用其他成員函數,經由(*fnPtr)()。如果這樣調用,該函數將無法訪問其成員數據(不知道this指針)。如果調用傳遞引用對象(即(*fnPtr)(obj)),該功能現在可以訪問成員數據。

我試圖通過指定一個通用的class type對象來解決這個問題,然後可以將Delegate other連接到任何成員。

+0

什麼會'other'依賴,以確定它是什麼? – 2012-01-16 20:35:44

+6

¤「請勿使用Boost或其他第三方庫」是自我毀滅的。你不想重新發明這個輪子,所以使用boost :: any或boost :: variant(我忘記了哪個是哪個)。或者使用該源代碼作爲起點,但不太可能改進它:使其無法提升的修改只會降低質量。無論如何,你爲什麼要這個?它確實看起來像**,你問的是一個預想的解決方案**,而不是詢問有關問題。如果是這樣,請詢問有關問題。 Cheers&hth。, – 2012-01-16 20:35:48

+1

「儘可能保持STL」(我假設你的意思是C++標準庫):你知道標準受Boost及其作者的影響嗎? – pmr 2012-01-16 20:40:39

回答

3

目前尚不清楚您嘗試解決什麼問題。在你的代碼中,class C的目的是什麼?無論如何,這是猜測你想要什麼。使用基本模板類implementation,該類從具有虛擬interface的公共基類中派生,並且generic類擁有指向該interface的指針。

class generic { 
    class interface { 
    public: 
     virtual ~interface(){} 
     virtual void SomeGenericMethod()=0; 
    }; 
    template <class T> 
    class implementation: public interface { 
     T data; 
    public: 
     implementation(const T& d) :data(d) {} 
     virtual void SomeGenericMethod() 
     {return data.SomeGenericMethod();} 
    }; 
    public: 
     std::unique_ptr<interface> data; 

     template < class T > void setOther(const T& other) { 
      data.reset(new implementation<T>(other)); 
     } 

     void doSomethingWithOther() { 
      data->SomeGenericMethod(); 
     } 
}; 

int main(int argc, char **argv) { 
    generic fObj; 
    Bar bObj; 
    fObj.setOther(bObj); 
    fObj.doSomethingWithOther(); 
    return 0; 
} 

​​

+0

嗨,'C類'是我現在使用的代碼中的簽名的一部分,它在泛型類的其他部分中使用,對於問題的結果並不重要,對於不澄清這一點很抱歉。無論如何,感謝您的回覆和提示,我會嘗試你的建議的變化,因爲我認爲它可能讓我走上正軌 – txtechhelp 2012-01-17 10:09:17

+0

好消息是我剛剛通知我現在可以實現C++ 0x和虛擬接口訣竅結束了完成我想要做的目標......謝謝! – txtechhelp 2012-01-17 18:09:41

+0

@txtechhelp:很高興能幫到你! 'unique_ptr'不是答案的關鍵,它只是防止錯誤。 – 2012-01-17 18:21:26

0

如果您在編譯時不知道確切的類型,則無法將其編碼爲模板參數。那些必須在編譯時知道,之後不能更改。請查看Boost.Any(任何可能的類型)或Boost.Variant(多種已知類型),以獲取可幫助您的示例。 any可以用合理的努力來實現,variant不是那麼多。考慮到你對C++模板的瞭解,你可能不應該試圖在沒有真正理解boost中的代碼的情況下實現,也不會有任何意圖。

+0

感謝您的信息,我將研究Boost庫如何實現其變體類型並查看它們是否可以提供幫助。不幸的是,由於嚴格的編碼強制,我不能帶任何第三方庫,否則這將是沒有意義的,哈哈。 – txtechhelp 2012-01-17 09:59:47

+0

但請不要嘗試自己實現它。 – pmr 2012-01-17 10:11:35

0

這聽起來像你的主要目標是調用other的某些成員函數。

如果是這樣的話,你甚至不需要other,而只是一個函數來封裝調用。例如。使用C++ 11或TR1:

template <class C> struct A { 
    C obj; 
    std::function<void()> op; 
    void f() { 
     // ... 
     op(); 
    } 
}; 

struct B { 
    void g() { std::cout << "moo" << std::endl; } 
}; 

int main() { 
    A<int> a; 
    B b; 
    a.op = std::bind(&B::g, &b); 
    a.f(); 
} 
+0

嗨格奧爾格,感謝您的信息,不幸的是我不能使用任何C++ 0x功能,這將有助於我目前的情況(無編譯器支持)。雖然我喜歡這個想法,因爲它的簡單性,我基本上想要在我的代碼中模擬這個功能,回到谷歌.. – txtechhelp 2012-01-17 10:22:10

+0

@txt:也許看看[快速代表](http://www.codeproject.com/ KB/cpp/FastDelegate.aspx),或者使用[bcp](http://www.boost。)提取'boost :: function'&'boost :: bind'。組織/ DOC /庫/ 1_48_0 /工具/ BCP/DOC/HTML/index.html的)? – 2012-01-17 17:21:33