2012-06-11 47 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; 
} 

考虑到你在你的问题,我会选择运行时提供的信息具有动态多态性的变体。