2010-08-18 147 views
2

考慮下面的模板:訪問模板中函數模板參數的結果類型?

 
template<class T> 
class Container 
{ 
private: 

    boost::function<T> f; 
}; 

...及其實例,也許如下:


    Container<bool(int, int)> myContainer; 

,是否有訪問函數描述的返回類型和條件編譯對抗的方式它?例如,如果調用者指定他的函數返回bool(如上例),我想包含一個返回值的函數。如果他指定該函數是無效的,我不希望包含該函數。例如:


// Include if the return type of T is void 
template<class T1, class T2> 
void DoSomething(T1 t1, T2 t2) 
{ 
    f(t1, t2); 
} 

// Include if the return type of T is not void 
template<class T1, class T2> 
***whatever the return type is*** DoSomething(T1 t1, T2 t2) 
{ 
    return f(t1, t2); 
} 

我猜這裏有一個解決方案,但它可能涉及一些可怕的混淆模板元編程解決方案。我知道格雷戈爾康托爾瘋了考慮無限......模板元編程種類對我有同樣的影響:頁。

感謝您的任何想法。

RobinsonT

編輯:顯然,這可以通過實現一個不同的類(可能是從一個共同的基衍生的),一個稱爲VoidContainer,另一個稱爲ReturnsContainer(或類似的)來解決。然而,這似乎有點不滿意...

+0

我認爲康託相當生氣,因爲他沒有從他的同時代人(和個人原因只有他自己知道)找到很多理解。你有SO社區的支持。 – UncleBens 2010-08-18 16:48:31

+0

是的。但我想我要麼會瘋狂地試圖理解,要麼SO社區會試圖解釋。無論哪種方式,都有人將他的褲子放在椅子上,每隻鼻孔上都放一支鉛筆。 – Robinson 2010-08-18 16:51:24

+0

這是Georg Cantor,不是Gregor Cantor。 – Henrik 2010-08-19 12:46:17

回答

3

我不認爲你真的需要專門爲返回void類型。在這種情況下,允許void函數返回另一個void函數的「結果」。

void foo() { } 
void bar() { return foo(); } //this is OK 

int main() 
{ 
    bar(); 
} 

所以你唯一的問題是如何確定返回類型。

看來,boost::functionresult_type一個typedef(見http://beta.boost.org/doc/libs/1_37_0/doc/html/boost/functionN.html

#include <boost/function.hpp> 


template<class T> 
class Container 
{ 
public: 
    typedef typename boost::function<T>::result_type result_type; 
private: 

    boost::function<T> f; 
}; 

Container<bool(int, int)>::result_type r = true; 

編輯: 現在你知道了result_type是什麼,你確實需要的空隙來區分/非無效的結果,你可以僱用enable_ifdisable_if。唯一複雜的是那些只能使用函數模板,所以非模板foo調用模板do_foo

#include <boost/function.hpp> 
#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits.hpp> 
#include <cstdio> 

template<class T> 
class Container 
{ 
public: 
    typedef typename boost::function<T>::result_type result_type; 


    result_type foo() 
    { 
     return do_foo<result_type>(); 
     //note that this still works because you can return the void result! :) 
    } 
private: 
    //use this if the result_type is void 
    template <class U> 
    typename boost::enable_if<boost::is_same<U, void>, U >::type do_foo() 
    { 
     std::puts("for void"); 
    } 

    //else 
    template <class U> 
    typename boost::disable_if<boost::is_same<U, void>, U>::type do_foo() 
    { 
     std::puts("other"); 
     return U(); 
    } 
private: 

    boost::function<T> f; 
}; 


int main() 
{ 
    Container<void()> a; 
    a.foo(); 

    Container<int()> b; 
    b.foo(); 
} 
+0

對於無效返回類型,這是真的,你不需要專注於上面給出的情況。但假設我有一個boost :: function 的集合,並且我想將每個調用的結果存儲到一個集合中,前提是DoSomething現在返回一個集合而不是:: result_type。在無效情況下,集合將無法編譯(std :: list ),事實上,即使它確實沒有任何意義。這就是爲什麼我想要區分這兩種情況的一些東西,並且如果T的返回類型是無效的,則不要嘗試實例化非void函數。 – Robinson 2010-08-18 17:20:47

+0

@robinsont:編輯的答案顯示如何使用'enable_if'來區分這兩種情況。 – UncleBens 2010-08-18 18:08:43

+0

非常感謝所有。這非常有幫助。 – Robinson 2010-08-18 18:18:55

3

是的,你可以使用boost::function_traits,它有一個result_type typedef。

+0

那將是什麼樣子?我確實玩過is_void和enable_if,但無法使用它們進行編譯。在上面的例子中,我可以寫is_void ,其中T是函數原型bool(int,int)?還是必須將result_type特徵傳遞給is_void函數?在這種情況下函數特徵是在T上。那麼,我寫函數_traits :: result_type? – Robinson 2010-08-18 16:58:04

+0

@robinsont:'is_void '如果'T'是一個函數類型,則爲false,因此,您基本上需要使用'boost :: is_void :: result_type> :: value' (或者接近於此;我沒有在這個lappy上測試Boost,而C++ 0x沒有'function_traits')。 – 2010-08-18 17:02:16

0

取決於你想如此,也許你正在做的事情比必要的更復雜。如果您在void案例中調用的f本身是無效函數,則可以保留return

明確地返回一個「空值」是確定的:

void f() { 
} 

void g() { 
    return f(); 
}