2012-06-11 49 views
0

我想創建一個類,它將有一個get模板方法,它將接收std :: string以在std :: map中查找正確的變量並將其返回。返回不同類型變量的單個get方法

性病::地圖應存儲任何類型的變量,所以我用的boost ::任何,迄今爲止的std ::地圖看起來像這樣:

std::map<std::string, boost::any> variables_; 

爲get函數,我試過的東西像這樣:

template <typename T> 
T get(std::string& parameter) 
{ 
    return variables_[parameter]; 
} 

但是沒有幸運,我的問題是,甚至有可能這樣做?如果是這樣,怎麼樣?

其基本思想是我不想爲我的類中的每個特定變量制定特定的方法,所以其他類不需要知道它的每個獲取方法。

謝謝!

ps:對於有人問我爲什麼要這樣做,這裏是一個簡歷,我有很多算法,它們將按照一定的順序運行,並且它將使用最後一個已運行的算法。所以,我想要的是製作一個xml文件,它將告訴哪些算法將運行,以何種順序以及將從另一個算法中使用哪些數據。因此,例如,算法A具有名爲「閾值」的變量,算法B需要該信息,因此,通常它將不得不使用類似於A.getThreshold的方式從A中請求它,但據我所知,我不能用一個字符串中的名稱(來自xml文件)調用一個對象函數,所以我的解決方案將只有一個get函數,我傳遞了我想要的變量名稱,該函數將它返回給我。

回答

2

另一種解決方案是將boost::any對象「包裝」到另一個對象中,該對象可以自動轉換爲任何您想要的對象。我認爲這不是一個好的做法,但根據你的問題,這是最合適的。

class AnyWrapper { 
    boost::any value; 
public: 
    AnyWrapper(const boost::any& val) : value(val) {} 
    template<typename T> operator T() { 
     return boost::any_cast<T>(value); 
    } 
} 

和你的getter會是這樣的:

AnyWrapper get(std::string& parameter) 
{ 
    return variables_[parameter]; // variables is a std::map<std::string, boost::any> 
} 

然後你應該能夠檢索您的元素那樣:

int integerValue = myContainer.get("age"); 
std::string stringValue = myContainer.get("name"); 

但同樣,這不是一個乾淨的解。有一個原因爲什麼提升作者選擇明確any_cast :)

1

boost::any值不會隱式轉換爲類型T,你有權要求手動施放:

template <typename T> 
T get(std::string& parameter) 
{ 
    return boost::any_cast<T>(variables_[parameter]); 
} 

通話將失敗,boost::bad_any_cast異常,如果存儲在any類型不是正好是T

0

您還可以返回boost::any。你失去了封裝你的實現,但取決於你如何使用返回值,這可能是更好的方法。

0

你想要的是不可能的,因爲你試圖混合編譯時(模板)和運行時(地圖查找)代碼。

你要麼必須使它完全運行:

struct base_type { virtual ~base_type{} }; 
struct derived_type: base_type { ... }; 
std::map<std::string, base_type*> lookup_map; 
base_type* get(std::string const& key) { return lookup_map[key]; } 

或完全編譯時間(例如boost.fusion):

#include <boost/fusion/container/map.hpp> 
#include <boost/fusion/sequence/intrinsic/at_key.hpp> 
#include <boost/fusion/sequence/intrinsic/value_at_key.hpp> 

namespace bf=boost::fusion; 

struct key_a; // analogues of string keys in compile time world 
struct key_b; 
struct key_c; 

typedef bf::map< 
    bf::pair<key_a, long>, 
    bf::pair<key_b, double>, 
    bf::pair<key_c, char const*> 
> rtmap_t; 
rtmap_t rtmap; 

template <class Key> 
void set_value(typename bf::result_of::value_at_key<rtmap_t, Key>::type const& val) 
{ 
    bf::at_key<Key>(rtmap) = val; 
} 

template <class Key> 
typename bf::result_of::at_key<rtmap_t, Key>::type get_value() 
{ 
    return bf::at_key<Key>(rtmap); 
} 

#include <iostream> 
int main() 
{ 
    char const* cval = "hello metaprogramming"; 
    set_value<key_a>(123l); 
    set_value<key_b>(456.789); 
    set_value<key_c>(cval); 
    std::cout << get_value<key_a>() << std::endl; 
    std::cout << get_value<key_b>() << std::endl; 
    std::cout << get_value<key_c>() << std::endl; 

    return 0; 
} 

考慮到你在你的問題,我會選擇運行時提供的信息具有動態多態性的變體。