2011-10-10 76 views
4

有一些類有這樣的方法:通用函數指針

int getSomething1(); 
std::string getSomething2(); 
someClass getSomething3(); 

有結構,描述這個類像的領域:

{"name of field", pointer to getter, std::type_info} 

然後我想用它,如下所示:

if(type == int){ 
    field_int = (int)getter(); 
} 
else if(type == std::string){ 
    field_string = (std::string)getter(); 
} 
etc. 

如何改造干將像

int getSomething1(); 
std::string getSomething2(); 
etc. 

給一些通用函數指針然後得到正確的字段值?

+1

我覺得,模板元編程是解決方案! – Nawaz

+0

你想在編譯時或運行時檢測到這個嗎? –

回答

2

This answer我的另一個問題很好地解決了你的問題。隨着一些小的修改,你會得到這樣的:

template<class C, class T> 
T get_attribute(const C& instance, T (C::*func)() const) { 
    return (instance.*func)(); 
} 

假設如下:

struct Foo { 
    int getSomething1() const; 
    std::string getSomething2() const; 
    someClass getSomething3() const; 
}; 

您可以使用它像這樣:

Foo foo; 
int value = get_attribute<Foo, int>(foo, &Foo::getSomething1); 
std::string value = get_attribute<Foo, std::string>(foo, &Foo::getSomething2); 
someClass value = get_attribute<Foo, someClass>(foo, &Foo::getSomething3); 

當然,你可以改變get_attribute的函子綁定一些或全部參數。

+0

我認爲這有點複雜 - 從這個問題來看,OP正在持有一個二級結構,應該存儲這些「pointer_to_something」.. – Nim

+0

@Nim:是的,我剛剛得到了。我相應地修改了它,它應該可以正常工作。 –

+2

@Nim這裏真正的問題是他想動態地選擇函數。函數本身是否是一個模板在這方面並沒有真正改變任何東西。 (正如所寫的,模板看起來像額外的語言;除了增加代碼行數外,它似乎沒有做任何具體的事情。) –

1

使用現有容器(如boost fusion序列)可以更好地實現您試圖實現的目標。我建議你先試試。

+0

@Bjorn,thx - 我通常只是使用最新版本 - 但該鏈接更好。 .. – Nim

0

模板來拯救!

// Create mapping of type to specific function 
template <typename T> T getSomething(); // No default implementation 
template <> int getSomething<int>() { return getSomething1(); } 
template <> std::string getSomething<std::string>() { return getSomething2(); } 
template <> someClass getSomething<someClass>() { return getSomething3(); } 
// Convenience wrapper 
template <typename T> void getSomething(T& t) { t = getSomething<T>(); } 
// Use 
int i = getSomething<int>(); 
std::string s; 
getSomething(s); 
+0

模板在這裏購買了什麼(除了額外的代碼行)? (如果你想在某種類中包裝呼叫,我可以看到使用該模板,但我需要更多地瞭解他的實際使用情況,以便能夠說出在這種情況下可能適合的內容。) –

1

沒有正式的通用函數指針的void* 數據相當。通常的解決方案是使用void (*)();您保證 您可以將任何(非成員)函數指針轉換爲此(或任何 其他函數指針類型)並返回而不丟失信息。

如果在函數簽名一定的相似性(例如,所有 是吸氣劑,不帶參數)以及它們是如何使用的,它可以是 可以與一個抽象基類和一組衍生 來處理這類(可能模板化);在地圖上放置這些 類的實例肯定會比一個巨大的 開關更優雅。

0

據我所知,你的困難在於存儲函數指針,因爲它們是不同的類型。你可以使用Boost.AnyBoost.Function來解決這個問題。

#include <boost/any.hpp> 
#include <boost/function.hpp> 

int getInt() { 
    return 0; 
} 

std::string getString() { 
    return "hello"; 
} 

int main() 
{ 
    boost::function<boost::any()> intFunc(getInt); 
    boost::function<boost::any()> strFunc(getString); 

    int i = boost::any_cast<int>(intFunc()); 
    std::string str = boost::any_cast<std::string>(strFunc()); 
}